gpt4 book ai didi

haskell - 非 IO 单子(monad)是否有可能违反 Haskell 中的关联性?

转载 作者:行者123 更新时间:2023-12-04 11:18:13 25 4
gpt4 key购买 nike

我是 Haskell 的新手,并试图更好地理解单子(monad)的结合律,它指出:

m >>= (\x -> k x >>= h) = (m >>= k) >>= h


通过尝试构建违反该定律的虚假单子(monad)。在高层次上,这条定律似乎在对我应用“一元函数”(不确定是否有合适的术语)时强制执行关联性。特别是,它看起来像是在执行 (f.g) x = f(g(x)) 的某个版本,翻译成单子(monad)。
然而,如果我们认为 f 和 g 是纯数学函数,那么这种关系似乎是微不足道的。这让我怀疑如果不涉及 IO,是否甚至可能违反这条定律,因为以我目前对 Haskell 的基本了解,这将确保 f 和 g 没有副作用。
我希望有人能详细说明我的总体思路是否正确,或者我是否有一些关键的误解,并且可以在不使用 IO 的情况下构建这样的反例。

最佳答案

我们集体历史中的一个标准示例是 ListT monad 转换器,它非常难以*正确。 The wiki对显而易见的实现出了什么问题以及如何修复它进行了完整的讨论,我将在此处摘录。它使用 following very plausible-looking "monad" instance :

newtype ListT m a = ListT { runListT :: m [a] }
instance (Monad m) => Monad (ListT m) where
return a = ListT $ return [a]
m >>= k = ListT $ do
a <- runListT m
b <- mapM (runListT . k) a
return (concat b)

instance (Monad m) => MonadPlus (ListT m) where
mzero = ListT $ return []
m `mplus` n = ListT $ do
a <- runListT m
b <- runListT n
return (a ++ b)
这是关联的反例:
a,b,c :: ListT IO ()
[a,b,c] = map (liftIO . putChar) ['a','b','c']

t1 :: ListT IO ()
t1 = ((a `mplus` a) >> b) >> c

t2 :: ListT IO ()
t2 = (a `mplus` a) >> (b >> c)

...running runListT t1 prints "aabbcc", while runListT t2 instead prints "aabcbc".


这个特殊的例子恰好使用了 IO ,但这不是基本的;我们也可以使用 ListT (Writer String)作为“单子(monad)”和 tell而不是 putChar .
*这个困难导致我们拥有一个庞大的密切相关的图书馆家族;该系列包括 list-t、logict、iteratee、machines、pipes、conduit 和 streamly。

关于haskell - 非 IO 单子(monad)是否有可能违反 Haskell 中的关联性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68070620/

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