在haskell中定义一个新的monad不会引发Applicative的实例

fak*_*ake 53 monads haskell

我试图定义一个新的monad,我得到一个奇怪的错误

newmonad.hs

newtype Wrapped a = Wrap {unwrap :: a}
instance Monad Wrapped where
  (>>=) (Wrap x) f =  f x
  return x = Wrap x

main = do
  putStrLn "yay"
$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 7.10.1

$ ghc newmonad.hs 
[1 of 1] Compiling Main             ( newmonad.hs, newmonad.o )

newmonad.hs:2:10:
    No instance for (Applicative Wrapped)
      arising from the superclasses of an instance declaration
    In the instance declaration for ‘Monad Wrapped’

为什么我需要定义一个实例Applicative

Mat*_*hid 83

这是申请Monad提案(AMP).现在每当你声明某些内容时Monad,你也必须将其声明为Applicative(因此Functor).从数学角度讲,每个monad 都是一个应用函子,所以这是有道理的.

您可以执行以下操作以删除错误:

instance Functor Wrap where
  fmap f (Wrap x) = Wrap (f x)

instance Applicative Wrap where
  pure = Wrap
  Wrap f <*> Wrap x = Wrap (f x)
Run Code Online (Sandbox Code Playgroud)

https://wiki.haskell.org/Functor-Applicative-Monad_Proposal

编辑:也许我应该更清楚地指出这是最近的事情?您发布的代码以前曾用过,但是对于最新版本的GHC,您将收到错误消息.这是一个突破性的变化.

编辑:以下声明应适用于任何 monad:

import Control.Applicative -- Otherwise you can't do the Applicative instance.
import Control.Monad (liftM, ap)

instance Functor ??? where
  fmap = liftM

instance Applicative ??? where
  pure  = return
  (<*>) = ap
Run Code Online (Sandbox Code Playgroud)

根据所讨论的monad,可能会有更高效的实现,但这是一个简单的起点.

  • 具体而言,最近版本的GHC成为错误,版本为7.10. (7认同)
  • 函数比Applicative更通用,Applicative比Monads更通用.功能强大(即您可以对它们执行的不同操作的数量)相反. (7认同)
  • 对于使用新教程等新人来说,这对于使用新GHC的人来说可能是一个常见的问题.为了使这个答案对其他人来说更有用,也许你可以给出一个`Applicative` /`Functor`定义,一般用于*所有*`Monad`s?(例如,使用`do`表示法,或`liftM`和`ap`(尽管那些需要导入.)) (7认同)
  • Monads让你只用普通的Applicative做一些不可能完成的事情.特别是,根据上一个操作的结果选择下一个要执行的操作. (6认同)
  • https://ghc.haskell.org/trac/ghc/wiki/Migration/7.10上的迁移指南说"请勿使用`pure = return`".(我现在不知道这意味着什么,我只是指出指南所说的内容) (2认同)
  • 我觉得很奇怪,Haskell不会自动从`Monad`实例派生出`Functor`和`Applicative`实例,并要求用户编写该样板文件. (2认同)