我对Haskell"衍生"的期望是什么?

8 haskell parametric-polymorphism

提前为初学者问题道歉,但我一直在努力寻找有用的信息.我正在努力学习"了解你的Haskell for Great Good",并且我正在尝试理解派生关键字,这似乎是Java的工具,但据说由于类别理论的东西或类似的东西,它可以用很酷的自动代码生成.我声明了一个2向量的数据结构

data R2 = R2 {x :: Double, y :: Double} deriving (Show)
Run Code Online (Sandbox Code Playgroud)

然后我可以用它来做类似的事情

show (R2 1.0 2.0)
Run Code Online (Sandbox Code Playgroud)

现在我想做的是矢量加法和标量乘法,比如

(2.0 * (R2 1.0 2.0)) + (R2 3.0 4.0)
Run Code Online (Sandbox Code Playgroud)

但是当我尝试

Prelude> data R2 = R2 { x :: Double, y :: Double} deriving (Num,Show)
     <interactive>:3:52:
     Can't make a derived instance of `Num R2':
         `Num' is not a derivable class
     In the data declaration for `R2'
Run Code Online (Sandbox Code Playgroud)

所以编译器想出了如何显示原始类型的笛卡尔积,但是加法太难了?也许Num不是正确的派生类型?有多少人可以期望派生一个类型类并在没有额外工作的情况下获得工作代码,比如我不必编写自己的show函数?

非常感谢,

约翰

dup*_*ode 6

试图理解派生关键字,这似乎是Java的工具,但据说有很酷的自动代码生成

instance有点像implements,因为你声明类型是类型类的实例然后编写实现.deriving是关于这些实现的很酷的自动生成(虽然它确实包含instance).

有多少人可以期望派生一个类型类并在没有额外工作的情况下获得工作代码,比如我不必编写自己的show函数?

Alexey Romanov的答案涵盖了哪些课程deriving有效.还有另一种自动生成实例的方法:使用泛型.从鸟瞰图来看,它的工作方式如下:您描述了一个实例对于泛型类型应该是什么样子,然后,对于您想要拥有实例的任何类型,派生Generic并添加一个空(即没有实现,因为它们将instance声明自动生成.有些库喜欢aesonbinary 提供随时可用的通用实例,您当然可以为您的类推送自己的实例.


Ale*_*nov 5

请参阅https://downloads.haskell.org/~ghc/7.10.2/docs/html/users_guide/deriving.html:

在Haskell 98中,可能出现在derinding子句中的唯一类是标准类Eq,Ord,Enum,Ix,Bounded,Read和Show.

GHC也允许推导Generic,Functor,Data,Typeable,FoldableTraversabledata申报,以及任何类newtype声明(启用相关的扩展之后,作为链接的页面列出).


Chr*_*lor 5

这是您无法派生Num类的原因之一

data Vector = Vector Int Int

instance Num Vector where
    Vector a b + Vector c d = Vector (a + c) (b + d)
    Vector a b * Vector c d = Vector (a * c) (b * d)

data Complex = Complex Int Int

instance Num Complex where
    Complex a b + Complex c d = Complex (a + c) (b + d)
    Complex a b * Complex c d = Complex (a * c - b * d) (a * d + b * c)
Run Code Online (Sandbox Code Playgroud)

两者都是真正的程序员可能想定义的明智实例。对于具有两个Int字段的给定数据定义,该deriving子句应选择哪个实例?

  • @ flagrant2您将如何定义Num类的signum方法,例如向量(1,-1)的符号是什么?在实现派生的“ Num”实例时要做出许多选择,以至于造成更多的麻烦。我认为编写自己的`Num`实例所需的额外5-6行并不是很多问题。公认的是,“ Num”类型类在Haskell中有点像疣,而且我相信有一些努力对其进行了改革,但进展缓慢,因为人们已经编写了依赖于当前实现的代码。 。 (4认同)