为什么这不是受限制的单子限制的情况?

5
在下面的代码片段中,我最初认为出现了受限制的单子错误(我忘记在instance Monad (Transform m a)定义中添加Monad m =>)。经过阅读关于受限制单子的许多文章后,我想知道为什么这里的代码是可以正常运行的:
{-# LANGUAGE GADTs #-}

data Next a where
    Todo :: a -> Next a
    Done :: Next a

instance Functor Next where
    fmap f Done = Done
    fmap f (Todo a) = Todo (f a)

data Transform m a b = Monad m => Transform ( m(Next a) -> m(Next b) )

instance Functor (Transform m a) where
    fmap f (Transform ta) = Transform tb where
        tb ma = ta ma >>= return . (fmap f)

instance Applicative (Transform m a) where
    pure = return
    mf <*> ma = do
        f <- mf
        a <- ma
        return (f a)

instance Monad m => Monad (Transform m a) where
    return b = Transform (t b) where                
        t b _ = return $ Todo b
    (Transform t) >>= f = Transform (\ma -> do     
        a <- ma
        case a of
            Done -> return Done
            --Todo a' -> ...
        )

这个例子有些牵强,我去掉了所有不相关的部分。(实际问题与这个相关。)关键部分是Transform中的Monad m限制。

我不太明白这与经常引用的典型Set作为单子的例子有何不同,后者确实展示了受限单子的限制。

2个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
6

Transform 不是受限制的单子。

看看 SetSet 在其一个参数上是单子,除非该参数需要是 Ord。也就是说,在所有对象都在 Ord 中的 Hask 子范畴中,Set 是一种单子。

但是 Transform 本来就不是一个单子。 Transform :: (* -> *) -> * -> * -> *,但是 Monad 应用于类型为 * -> * 的东西(如果你要全面地理解范畴论,通常情况下,单子是恒等函子,应该大致具有类型为 k -> k 的某些 k,但是 Transform 也不完全符合这种更广泛的模板)。成为单子的是 m 是单子时的 Transform m a。只要 m 也是单子,Transform m a 就是对于 Hask 中的所有类型而言的单子。你看出��别了吗?由于 Set 是单子的参数受到限制,因此没有任何东西可以填充空白以使“Set 给定 ___ 在每个类型上都可以操作”,而 Transform m a 并没有对其其单子所作用的类型施加限制,而是对构成其一部分的某些类型施加了限制。


我希望人们更经常使用范畴语言... 是的,现在很清楚了! - mcmayer
很好的回答,但我想指出Set需要Ord,而不仅仅是Eq - Mor A.
@M.Aroosi 已修复。 - HTNW

4
我不太清楚这与常被引用的 Set 作为单子的规范示例有何不同,后者确实展示了受限单子的限制。 它的不同之处在于约束条件不在最后一个类型参数上,而在 Monad 中变化的那个。但在 Set 的情况下,它就在最后一个类型参数上。

那个替代定义与问题中的定义是相同的,不是吗? - HTNW
哦,我错过了限制的位置,请原谅。 - Alexey Romanov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,