假设两个新类型的定义如下所示
type MyProductType a = (FType1 a, FType2 a)
type MyCoproductType a = Either (FType1 a) (FType2 a)...and,FType1和Ftype2都是Functor的实例。
如果现在将MyProductType和MyCoproductType声明为Functor的实例,编译器是否需要对它们各自的fmap进行显式定义,还是可以从前面的定义中推断出这些定义?
另外,这个问题的答案是依赖于实现的,还是来自Haskell规范?
作为背景,这个问题的动机是试图理解我正在读的东西中的一句话。作者首先定义了
type Writer a = (a, String)...and后来写到(我的重点)
...the
Writer类型构造函数是a中的函数。我们甚至不需要为它实现fmap,因为它只是一个简单的产品类型。
强调的文本是我想要理解的注释。我认为这意味着Haskell可以根据函数式类型推断出任何ADT的fmap,特别是,它可以推断出像Writer这样的“简单产品类型”的fmap,但现在我认为这种解释是不正确的(至少如果我正确地阅读了厄詹·约翰森的答案)。
至于作者所说的那句话是什么意思,我现在真的一无所知。也许他的意思是,用这样一种方式重新定义Writer是不值得的,因为它是一种“简单的.类型”。(在这里抓吸管)
发布于 2015-09-20 15:13:59
首先,您通常不能为type同义词定义新实例,特别是不能像在您的情况下所需要的那样部分应用实例。我认为您的意思是定义newtype或data,而不是:
newtype MyProductType a = MP (FType1 a, FType2 a)
newtype MyCoproductType a = MC (Either (FType1 a) (FType2 a))标准Haskell完全没有提到自动派生Functor,这只有在GHC的DeriveFunctor扩展中才有可能。(有时是GeneralizedNewtypeDeriving,但这在示例中不适用,因为您没有使用a作为构造函数中的最后一个参数。)
所以让我们试试:
{-# LANGUAGE DeriveFunctor #-}
data FType1 a = FType1 a deriving Functor
data FType2 a = FType2 a deriving Functor
newtype MyProductType a = MP (FType1 a, FType2 a) deriving Functor
newtype MyCoproductType a = MC (Either (FType1 a) (FType2 a)) deriving Functor我们得到错误消息:
Test.hs:6:76:
Can't make a derived instance of ‘Functor MyCoproductType’:
Constructor ‘MC’ must use the type variable only as the last argument of a data type
In the newtype declaration for ‘MyCoproductType’结果表明,GHC可以导出前三个,但不能导出最后一个。我认为第三种只有因为元组是特殊的大小写才起作用的。但是,Either不起作用,因为GHC没有对Either如何对待其第一个参数保持任何特殊的知识。在这个论点中,它名义上是一个数学函子,但不是Haskell Functor。
请注意,GHC只将变量用作已知为Functors的类型的最后一个参数是更明智的。
newtype MyWrappedType a = MW (Either (FType1 Int) (FType2 (Maybe a))) deriving Functor总之:它取决于,GHC对此有一个扩展,但是它并不总是足够聪明来做你想做的事情。
https://stackoverflow.com/questions/32680771
复制相似问题