Haskell - 自动 Monad 实例

7
我正在尝试创建自己的数据类型,这将是Monad类的一部分,但是...
newtype Container a = Container a deriving Monad

出现了这个错误:

   * Can't make a derived instance of `Monad Container'
        (even with cunning GeneralizedNewtypeDeriving):
        cannot eta-reduce the representation type enough
    * In the newtype declaration for `Container'
   |
30 | newtype Container a = Container a deriving Monad

对于其他类(例如Show),它能很好地工作,但是对于Monad类却不行,那么我该如何让ghci将我的Container实例化为Monad类呢?

谢谢。


1
问题在于 a 不是一个 monad 实例,因此它没有太多意义。例如,如果您使用 newtype Container a = Container [a] deriving (Functor, Applicative, Monad),它将起作用,因为 []Monad 的一个实例。 - Willem Van Onsem
2
GenerlizedNewtypeDeriving 是专门用于将包装类型的实例提升到新类型的。如何(或是否)可以自动为 Container 派生一个 Monad 实例仍然是有趣的问题。(base 定义了 IdentityMonad 实例,这表明您不能这样做。) - chepner
“Monad”不是Haskell标准提供的可以自动派生的类型类之一(例如,“Show”以及其他一些基本类型类)。但是,使用正确的扩展,GHC可以实现它。 - Robin Zigmond
请注意,该消息表明启用了“GeneralizedNewtypeDeriving”,但问题是为什么它仍然无法正常工作。 - Alexey Romanov
1个回答

9
对于其他类(例如Show),它可以正常工作。
只有一组固定的标准类支持直接派生:
在Haskell 98中,唯一可派生的类是Eq,Ord,Enum,Ix,Bounded,Read和Show。各种语言扩展扩展了这个列表。 --- GHC用户手册
特别地,Monad不属于该列表,也不属于扩展列表。
还有更多的扩展将推广到任意类的派生,但无法100%自动化。某个地方必须指定如何执行此派生;根据类别,用户可能需要承担负担,因为基本上不能推断出某些信息。
在您的情况下,新类型Container在标准库中表示与Identity monad等效,因此您可以使用DerivingVia:
{-# LANGUAGE DerivingVia #-}
import Data.Functor.Identity

newtype Container a = Container a deriving (Functor, Applicative, Monad) via Identity

在这种非常特殊的情况下,只有一个明智的实例,但大多数情况下,即使只有一个实例,也很难确定它应该是什么。

你还需要派生FunctorApplicative,然后将Container 3 >>= (+1)的类型与Identity 3 >>= (+1)进行比较。我不知道这是否与DerivingVia有关。 - chepner
(如果我做了什么奇怪的事情,我得到了Container 3>> = (+1) :: Num(Container b)=> Container bIdentity 3>> = (+1) :: Num b => Identity b。我不确定为什么“Container b”而不是“b”具有“Num”约束。) - chepner
感谢您的准确性。至于您的第二条评论,要将 (+ 1) :: Num c => c -> c 作为 Kleisli 箭头 (+ 1) :: a -> Container b,您需要统一 c ~ Container b。但我不确定您的观点是什么。 - Li-yao Xia
我只是想知道Identity定义了什么,而Container没有定义,因为Identity 3 >>= (+1)的结果是Identity 4 - chepner
这是因为定义了一个 instance Num a => Num (Identity a) - K. A. Buhr
哦,嗯。谢谢。 - chepner

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