如何在Haskell中实现带String日志的Writer函子?解决类型错误
问题解决:Haskell中Writer函子的实现错误
错误原因
你遇到的错误提示“类型同义词‘Writer’应该有1个参数,但被传入了0个”,本质是Haskell默认不允许为类型同义词(type定义的别名)定义类型类实例。你用type Writer a = (a,String)定义的Writer只是(a,String)的别名,并非独立的类型构造器,无法直接作为Functor实例的主体。
解决方案
有两种可行的修复方式,推荐使用第一种更规范的方案:
方案1:用newtype定义独立的Writer类型
newtype会创建一个全新的类型(运行时无额外开销),符合Haskell类型类实例的要求:
newtype Writer a = Writer (a, String) instance Functor Writer where fmap :: (a -> b) -> Writer a -> Writer b fmap f (Writer (x, s)) = Writer (f x, s)
这里我们用Writer构造器包装元组,fmap时先解包、映射值、再重新包装,完美对应你想要的f × id_c函子行为——只映射第一个分量(对应范畴中的对象a),保持第二个分量(日志String,对应范畴中的对象c)不变。
方案2:开启扩展支持类型同义词实例
如果你坚持要用类型同义词,需要在代码顶部开启两个GHC扩展,允许为类型同义词定义实例:
{-# LANGUAGE TypeSynonymInstances #-} {-# LANGUAGE FlexibleInstances #-} type Writer a = (a, String) instance Functor Writer where fmap f (x, s) = (f x, s)
但这种方式不推荐,因为类型同义词是现有类型的别名,可能引发类型歧义,破坏类型安全性。
内容的提问来源于stack exchange,提问作者CCB
相关产品推荐
相关产品推荐

