Given the below program, I am having issues dealing with monads.
module Main
where
import System.Environment
import System.Directory
import System.IO
import
Use case
.
main = do
...
case csv_data of
Left err -> {- whatever you're going to do with an error -- print it, throw it as an exception, etc. -}
Right csv -> printCSV csv
The either
function is shorter (syntax-wise), but boils down to the same thing.
main = do
...
either ({- error condition function -}) printCSV csv_data
You must unlearn what you have learned.
Master Yoda.
In languages like Haskell, functions are first-class values, just like those of Bool, Char, Ints, Integers, and other Haskell types e.g:
map :: (a -> b) -> [a] -> [b]
or:
(>>=) :: Monad m => m a -> (a -> m b) -> m b
So pure functions can be lifted into manifestly effect-centric contexts (as denoted by the type system), unlike what happens in most other programming languages which are first-order and have pervasive effects.
Instead of thinking about, or searching for ways to "free", "liberate", "unwrap" or "extract" pure values from those effect-centric contexts (usually monadic!), divert as much code as possible into pure functions and pass them around to wherever they're needed, just like values of any other type in regular Haskell.
All going well, you'll end up with most of your code being purely (and plainly!) functional, leaving the effects to a vanishingly-small set of entities defined in terms of functors, applicatives, monads, arrows, etc.
Will this always work? No - Haskell is in many ways the pioneer in its space, much as Fortran was in its early days. To expect new projects to get everything right from the outset is to invite disappointment and Haskell is no exception.
But if you are disappointed, you can have a look at Standard ML, OCaml, and other similar languages - maybe you'll be happier with using them :-)
Regarding monads:
Yes, Either a
is a monad. So simplifying the problem, you are basically asking for this:
main = print $ magicMonadUnwrap v
v :: Either String Int
v = Right 3
magicMonadUnwrap :: (Monad m) => m a -> a
magicMonadUnwrap = undefined
How do you define magicMonadUnwrap
? Well, you see, it's different for each monad. Each one needs its own unwrapper. Many of these have the word "run" in them, for example, runST
, runCont
, or runEval
. However, for some monads, it might not be safe to unwrap them (hence the need for differing unwrappers).
One implementation for lists would be head
. But what if the list is empty? An unwrapper for Maybe
is fromJust
, but what if it's Nothing
?
Similarly, the unwrapper for the Either
monad would be something like:
fromRight :: Either a b -> b
fromRight (Right x) = x
But this unwrapper isn't safe: what if you had a Left
value instead? (Left usually represents an error state, in your case, a parse error). So the best way to act upon an Either
value it is to use the either
function, or else use a case statement matching Right
and Left
, as Daniel Wagner illustrated.
tl;dr: there is no magicMonadUnwrap
. If you're inside that same monad, you can use <-
, but to truly extract the value from a monad...well...how you do it depends on which monad you're dealing with.