【问题标题】:Why is ListT monad transformer considered buggy - what monad laws it breaks?为什么 ListT monad 转换器被认为是错误的 - 它违反了哪些 monad 法则?
【发布时间】:2012-09-19 00:49:39
【问题描述】:

我看到有人提到过

ListT 是一个不满足 monad laws 的错误单子转换器的经典示例。

这可以通过一个简单的例子来证明吗?

编辑:我对@9​​87654325@ 的想法有点错误,我错过了documentation 要求内部单子是可交换的。那么,ListT buggy 只是在有这个要求的意义上,还是还有其他问题? (examples at Haskell wiki 都使用ListT IOIO 显然是不可交换的。)

【问题讨论】:

    标签: haskell functional-programming monads monad-transformers


    【解决方案1】:

    一个简单的例子说明它是如何违反结合律的:

    v :: Int -> ListT [] Int
    v 0 = ListT [[0, 1]]
    v 1 = ListT [[0], [1]]
    
    main = do
        print $ runListT $ ((v >=> v) >=> v) 0
        -- = [[0,1,0,0,1],[0,1,1,0,1],[0,1,0,0],[0,1,0,1],[0,1,1,0],[0,1,1,1]]
        print $ runListT $ (v >=> (v >=> v)) 0
        -- = [[0,1,0,0,1],[0,1,0,0],[0,1,0,1],[0,1,1,0,1],[0,1,1,0],[0,1,1,1]]
    

    更多示例(主要使用IO)以及如何修复ListT 的解决方案可以在ListT done right 找到。

    【讨论】:

    • 文档说转换后的 monad 必须是可交换的;尝试一下,例如v n = ListT $ map (read :: String -> Int) . permutations . show . (+n)
    • 嗯...它们被称为“monad 转换器”,而不是“commutative monad 转换器”。如果我定义了一个仅在应用于几个特定 monad 时才能正常工作的转换器,有人会认为这令人满意吗?
    • @C.A.McCann 真的。让我感到困惑的是,即使 ListT 的问题是已知的,甚至有一个建议的解决方案 (ListT done right),它仍然以这种形式保留在 Haskell 的标准库中。
    • ListT 在这些方面的版本未能正确捕捉到[] 的许多用途,但具体而言,将列表视为多重集而不是序列的用途,即有限列表元素的顺序无关紧要。当然,这正是问题所在——损坏的 ListT 假定内部 monad 中 (>>=) 应用程序的顺序也无关紧要,而“正确完成”版本在 (可能无限)流。后者捕获了“列表作为控制结构”的想法,因此与迭代式流有关。
    • @applicative 是的,添加这样的类会很有帮助。我们可以简单地拥有class Monad m => MonadCommutative mMonadTrans 也是如此)而无需其他方法。那么任何可交换的方法都会被这个类简单地标记。
    猜你喜欢
    • 2012-11-21
    • 1970-01-01
    • 2018-01-24
    • 1970-01-01
    • 1970-01-01
    • 2012-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多