繁体   English   中英

Haskell Monadic forms

[英]Haskell Monadic forms

一个简单的问题:给定定义,(来自 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。

是的?

让我们在Maybe monad 中做一个简单的例子:

foo = do
        let x = Just 1
        return x

bar = do
        x <- Just 1
        return x

对两者都进行脱糖,我们得到

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

作为参考,我使用的是 Haskell 2010 报告第 3.14 节的翻译

不,它们不一样。 例如,

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 -notation 中, let像往常一样将值绑定到名称,而<-用于执行单子绑定,即将名称绑定到计算结果

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

let版本中,当您在 do 表达式中使用x时,您正在处理Monad m => ma类型的值。

在另一个版本中,当您在 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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM