Unwrapping a monad

后端 未结 3 1355
Happy的楠姐
Happy的楠姐 2020-12-04 02:06

Given the below program, I am having issues dealing with monads.

module Main 
where
import System.Environment
import System.Directory
import System.IO
import         


        
相关标签:
3条回答
  • 2020-12-04 02:46

    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
    
    0 讨论(0)
  • 2020-12-04 02:53

    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 :-)

    0 讨论(0)
  • 2020-12-04 03:01

    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.

    0 讨论(0)
提交回复
热议问题