开发者

Haskell Monadic forms

A simple question: given the definitions, (From Haskell SOE)

   do x — el; el\ ...; en 
    => el »= \x — do e2\ ...; en 

and:

do let decllist; el\...; en 
=> let decllist in do e2\ ...; en 

it seems that these two constructs are the same:

do let x = e1
   e2

and

do x <- e1
   e2
开发者_开发知识库

both evaluate e1, bind it to e2, and then evaluate e2.

Yes?


Let's do a simple example in the Maybe monad:

foo = do
        let x = Just 1
        return x

and

bar = do
        x <- Just 1
        return x

Desugaring both, we get

foo = let x = Just 1 in return x    -- do notation desugaring
    = return (Just 1)               -- let
    = Just (Just 1)                 -- definition of return for the Maybe monad

bar = let ok x = return x in Just 1 >>= ok   -- do notation desugaring
    = let ok x = return x in ok 1   -- definition of >>= for the Maybe monad
    = return 1                      -- definiton of ok
    = Just 1                        -- definition of return for the Maybe monad

For reference, I am using the translation from section 3.14 of the Haskell 2010 Report.


No, they are not the same. For example,

do let x = getLine
   print x

translates to

let x = getLine in print x

this is a type error, as x will have the type IO String. We're asking to print the computation itself, not its result.


do x <- getLine
   print x

translates to

getLine >>= \x -> print x

Here x is bound as the result of the computation and its type is String, so this type checks.


In do-notation, let just binds values to names like it always does, while <- is used to perform monadic binding, which is binding a name to the result of a computation.


Assuming e1 is a computation of type Monad m => m a, then let x = e1 and x <- e1 mean somewhat different things.

In the let-version, when you use x within a do-expression, you are dealing with a value of type Monad m => m a.

In the other version, when you use x within a do expression, you are dealing with a value of type a (since do-notation implicitly handles mapping over the monad).

For example:

e :: IO Int
f :: Int -> Int

-- the following will result in a type error, since f operates on `Int`, not `IO Int`:
g = do let x = e
       return $ f x

-- the following will work:
g' = do x <- e
        return $ f x


No. x <- e1 translates to e1 >>= \x ->, an incomplete expression; the let expression is just a normal let. Or are you asking if let and (>>=) are the same thing? They very much aren't: (>>=) exposes the thing wrapped by a monad to a function, which must produce something wrapped in the monad. In other words, with x <- e1, e1's type must be IO a for some a, but with let x = e1 e1's type is just a; in both cases the type of x will be a.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜