Haskell “Monad(编写器字符串)”的非法实例声明

Haskell “Monad(编写器字符串)”的非法实例声明,haskell,monads,Haskell,Monads,我尝试创建自己的书写类型,之后我还为其创建了一个实例。不管怎么说,我一直都会遇到这样的错误: Illegal instance declaration for ‘Monad (Writer String)’ (All instance types must be of the form (T a1 ... an) where a1 ... an are *distinct type variables*, and each type variable appears at mos

我尝试创建自己的书写类型,之后我还为其创建了一个实例。不管怎么说,我一直都会遇到这样的错误:

Illegal instance declaration for ‘Monad (Writer String)’
  (All instance types must be of the form (T a1 ... an)
   where a1 ... an are *distinct type variables*,
   and each type variable appears at most once in the instance head.
   Use FlexibleInstances if you want to disable this.)
In the instance declaration for ‘Monad (Writer String)’
这是我的代码:

newtype Writer log a = Writer {runWriter :: (a,log)} 
instance Monad (Writer String) where
  return a = Writer (a, "")
  ma >>= k = let (a, log1) = runWriter ma 
                 (b, log2) = runWriter (k a)
             in Writer (b, log1 ++ log2)
所有实例类型的格式必须为T a1。。。一个

…意思是,你可以写

instance Monad (Writer a) where ...
但不是

instance Monad (Writer String) where ...
因为字符串不是类型变量

这只是Haskell自1998年以来的一个愚蠢的限制。显然,这个限制使编写编译器变得更容易,我不知道。每个人都使用FlexibleInstances扩展,它已在GHC中使用多年,并禁用了该限制

{-# LANGUAGE FlexibleInstances #-}
newtype Writer log a = Writer {runWriter :: (a,log)} 
instance Monad (Writer String) where
  ...
或者,您可以使用更多态的实例,但是Monad Writer a不太起作用,因为您需要能够拥有空日志和连接日志。标准解决方案是为可连接类型调用泛型类:

import Data.Monoid

instance Monoid a => Monad (Writer a) where
  return a = Writer (a, mempty)
  ma >>= k = let (a, log1) = runWriter ma 
                 (b, log2) = runWriter (k a)
             in Writer (b, log1 <> log2)
另一方面,要拥有Monad实例,还必须首先实例化

所有实例类型的格式必须为T a1。。。一个

…意思是,你可以写

instance Monad (Writer a) where ...
但不是

instance Monad (Writer String) where ...
因为字符串不是类型变量

这只是Haskell自1998年以来的一个愚蠢的限制。显然,这个限制使编写编译器变得更容易,我不知道。每个人都使用FlexibleInstances扩展,它已在GHC中使用多年,并禁用了该限制

{-# LANGUAGE FlexibleInstances #-}
newtype Writer log a = Writer {runWriter :: (a,log)} 
instance Monad (Writer String) where
  ...
或者,您可以使用更多态的实例,但是Monad Writer a不太起作用,因为您需要能够拥有空日志和连接日志。标准解决方案是为可连接类型调用泛型类:

import Data.Monoid

instance Monoid a => Monad (Writer a) where
  return a = Writer (a, mempty)
  ma >>= k = let (a, log1) = runWriter ma 
                 (b, log2) = runWriter (k a)
             in Writer (b, log1 <> log2)

另一方面,要拥有Monad实例,您必须首先实例化。

好的,谢谢!现在我得到了这个“Monad Writer String”的实例声明中实例声明的超类产生的应用程序编写器字符串没有实例是的,这就是我的意思。您需要先定义实例应用程序编写器字符串,然后才能使用monad实例。好的,谢谢!现在我得到了这个“Monad Writer String”的实例声明中实例声明的超类产生的应用程序编写器字符串没有实例是的,这就是我的意思。您需要先定义实例应用程序编写器字符串,然后才能拥有monad实例。