gpt4 book ai didi

haskell - IO monad防止嵌入式mapM短路?

转载 作者:行者123 更新时间:2023-12-04 02:07:06 26 4
gpt4 key购买 nike

下面的代码有点神秘。在问题的非玩具版本中,我试图在 monad Result 中进行 monadic 计算,其值只能从 IO 中构造。似乎 IO 背后的魔力使此类计算变得严格,但我无法弄清楚这是如何发生的。

编码:

data Result a = Result a | Failure deriving (Show)

instance Functor Result where
fmap f (Result a) = Result (f a)
fmap f Failure = Failure

instance Applicative Result where
pure = return
(<*>) = ap

instance Monad Result where
return = Result
Result a >>= f = f a
Failure >>= _ = Failure

compute :: Int -> Result Int
compute 3 = Failure
compute x = traceShow x $ Result x

compute2 :: Monad m => Int -> m (Result Int)
compute2 3 = return Failure
compute2 x = traceShow x $ return $ Result x

compute3 :: Monad m => Int -> m (Result Int)
compute3 = return . compute

main :: IO ()
main = do
let results = mapM compute [1..5]
print $ results
results2 <- mapM compute2 [1..5]
print $ sequence results2
results3 <- mapM compute3 [1..5]
print $ sequence results3
let results2' = runIdentity $ mapM compute2 [1..5]
print $ sequence results2'

输出:
1
2
Failure
1
2
4
5
Failure
1
2
Failure
1
2
Failure

最佳答案

不错的测试用例。这是正在发生的事情:

  • mapM compute像往常一样,我们看到工作中的懒惰。这里没有惊喜。
  • mapM compute2我们在 IO monad 内部工作,它的 mapM定义将需要整个列表:不像 Result一旦 Failure 跳过列表的尾部已找到,IO将始终扫描整个列表。注意代码:
    compute2 x = traceShow x $ return $ Result x

    因此,只要访问了 IO 操作列表的每个元素,上述内容就会打印调试消息。都是,所以我们打印所有内容。
  • mapM compute3我们现在大致使用:
    compute3 x = return $ traceShow x $ Result x

    现在,自从 return在 IO 是惰性的,它不会触发 traceShow返回 IO 操作时。所以,当 mapM compute3正在运行,没有看到任何消息。相反,我们仅在 sequence results3 时才看到消息。运行,这会强制 Result - 不是所有的,但只有需要的。
  • 决赛 Identity例子也很棘手。请注意:
    > newtype Id1 a = Id1 a
    > data Id2 a = Id2 a
    > Id1 (trace "hey!" True) `seq` 42
    hey!
    42
    > Id2 (trace "hey!" True) `seq` 42
    42

    使用 newtype 时,在运行时不涉及装箱/拆箱(AKA 提升),因此强制 Id1 x值(value)导致x被迫。与 data类型这不会发生:值被包装在一个盒子里(例如 Id2 undefined 不等于 undefined )。

    在您的示例中,您添加了 Identity构造函数,但来自 newtype Identity !!所以,打电话的时候
    return $ traceShow x $ Result x
    return这里不包装任何东西,traceShow立即触发 mapM正在运行。
  • 关于haskell - IO monad防止嵌入式mapM短路?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37538532/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com