Haskell - 自动 Monad 实例

Edw*_*rey 8 monads haskell instance deriving newtype

我正在尝试创建自己的数据类型,它将成为 Monad 类的一部分,但是

newtype Container a = Container a deriving Monad
Run Code Online (Sandbox Code Playgroud)

给我这个错误:

   * 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
Run Code Online (Sandbox Code Playgroud)

它适用于其他类(例如 Show),但不适用于 Monad,那么我如何说服 ghci 将我的 Container 实例化为 Monad 类?

谢谢

Li-*_*Xia 9

它适用于其他类(例如显示)

只有一组固定的标准类支持开箱即用的派生:

在 Haskell 98 中,唯一可派生的类是 Eq、Ord、Enum、Ix、Bounded、Read 和 Show。各种语言扩展扩展了这个列表。

--- GHC 用户手册

特别Monad是不属于该列表,也不属于扩展列表。

有更多扩展可以将派生推广到任意类,但它们不能 100% 自动化。某个地方的某个人必须指定如何进行推导;根据类别,用户可能需要承担负担,因为存在根本无法推断的信息。

在您的情况下, newtypeContainer在表示上等同Identity于标准库中的monad,因此您可以使用DerivingVia

{-# LANGUAGE DerivingVia #-}
import Data.Functor.Identity

newtype Container a = Container a deriving (Functor, Applicative, Monad) via Identity
Run Code Online (Sandbox Code Playgroud)

在这种非常特殊的情况下,只有一个合理的实例,但大多数情况下,即使只有一个,也不容易判断实例应该是什么。