制作 Haskell 个 Monad

Making Haskell Monads

我正在尝试在 Haskell 中创建一个非常简单的 monad。 monad 没有做任何特别的事情,只是持有一个计数器作为状态。

module EmptyMonad
  ( EmptyMonad
  ) where

import Control.Monad

data EmptyMonad a = EmptyMonad
  { myValue :: a
  , myState :: Int
  } deriving (Show)

instance (Eq a) => Eq (EmptyMonad a) where
  EmptyMonad x1 y1 == EmptyMonad x2 y2 = x1 == x2 && y1 == y2


instance Monad (EmptyMonad a) where
  return x = EmptyMonad x 0
  (EmptyMonad x y) >>= f = EmptyMonad x (y + 1)

在 Monads 上花了几个小时后,我无法理解编译器的错误:

EmptyMonad.hs:16:10: error:
    • Expecting one fewer argument to ‘Monad EmptyMonad’
      Expected kind ‘k0 -> Constraint’,
        but ‘Monad EmptyMonad’ has kind ‘Constraint’
    • In the instance declaration for ‘Monad EmptyMonad a’
Failed, modules loaded: none.

这里主要有两个问题:

  • 实例声明期望一种种类* -> *。所以比如 [], 而不是 [a];和
  • 绑定运算符 >>= 需要一个 EmptyMonad a 和一个函数 a -> EmptyMonad b 和 returns 一个 EmptyMonad b 元素。

因此我们可以通过以下解决方案解决问题:

instance Monad EmptyMonad where  -- no a after EmptyMonad
  return x = EmptyMonad x 0
  (EmptyMonad x y) >>= f = fx {myState = y+1}
      where fx = f x

所以这里我们指定 instance Monad EmptyMonad 因为 EmptyMonad 有种类 * -> *。此外,绑定运算符将计算 f x,然后使用 y+1.

更改该实例的 myState

话虽这么说,现在您还需要使 EmptyMonad 成为 ApplicativeFunctor 的实例。