Haskell Monadic形式

时间:2011-07-06 15:57:02

标签: haskell monads

一个简单的问题: 根据定义,(来自Haskell SOE)

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

和:

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

似乎这两个结构是相同的:

do let x = e1
   e2

do x <- e1
   e2

评估e1,将其绑定到e2,然后评估e2。

4 个答案:

答案 0 :(得分:4)

让我们在Maybe monad:

中做一个简单的例子
foo = do
        let x = Just 1
        return x

bar = do
        x <- Just 1
        return x

Desugaring both,我们得到了

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

供参考,我使用的是translation from section 3.14 of the Haskell 2010 Report

答案 1 :(得分:3)

不,他们不一样。例如,

do let x = getLine
   print x

转换为

let x = getLine in print x

这是类型错误,因为x的类型为IO String。我们要求打印计算本身,而不是结果。


do x <- getLine
   print x

转换为

getLine >>= \x -> print x

此处x作为计算结果绑定,其类型为String,因此此类型会检查。


do - 表示法中,let只是将值绑定到名称一样,而<-用于执行monadic绑定,即将名称绑定到结果计算。

答案 2 :(得分:1)

假设e1Monad m => m a类型的计算,那么let x = e1x <- e1意味着有些不同。

let - 版本中,当您在do-expression中使用x时,您正在处理类型为Monad m => m a的值。

在另一个版本中,当您在do表达式中使用x时,您正在处理类型a的值(因为do-notation隐式处理monad上的映射)。

例如:

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

答案 3 :(得分:0)

没有。 x <- e1转换为e1 >>= \x ->,表达不完整; let表达式只是普通let。或者您在问let(>>=)是否相同?它们非常不是:(>>=)将monad包装的东西暴露给一个函数,该函数必须生成包含在monad中的东西。换句话说,对于x <- e1,某些e1的{​​{1}}类型必须为IO a,但a let x = e1的类型为只是e1;在这两种情况下,a的类型都是x