如何成为特定类型?

时间:2017-08-03 06:11:24

标签: haskell

我有以下代码段:

Prelude Data.Monoid> :t 1 <> (2 :: Sum Integer)
1 <> (2 :: Sum Integer) :: Sum Integer

1如何成为Sum Integer类型?

更新

我使用mappend功能玩了一下并发现:

Prelude Data.Monoid> x = mappend 43

为什么mappend接受号码4343Num类型,它没有monoid实例。

1 个答案:

答案 0 :(得分:5)

首先(2 :: Sum Integer)

Haskell中的任何文字整数都由Haskell通过将其包装在fromInteger调用中来重写。所以:

(2 :: Sum Integer) == ((fromInteger (2 :: Integer)) :: Sum Integer) 

Haskell只允许左侧的符号,因此更容易输入,但它等同于右侧的代码。

fromInteger函数具有以下类型签名:

fromInteger :: Num a => Integer -> a

因此(fromInteger (2 :: Integer))的类型为Num a => a

在图书馆的某个地方,您将拥有如下所示的实例:

instance Num a => Num (Sum a) where ...

由于IntegerNum,因此Sum Integer

因此我们只需替换Num a => a即可将Sum Integer转换为a = Sum Integer

最后,我们有Semigroup函数:

(&lt;&gt;):: Semigroup a =&gt; a - &gt; a - &gt;一个

还有一个例子:

instance Num a => Semigroup (Sum a) where ...

在semigroups模块中的某个地方,并且(<>)函数指定左右参数和结果必须是相同的参数,那么如果我们知道其中一个,我们就知道其他两个。我们知道正确的参数是Sum Integer,所以我们必须检查我们是否可以将左参数转换为Sum Integer

从以前开始,1确实意味着fromInteger (1 :: Integer)。我们之前已经提到了fromInteger Sum Integer的实现,所以这很好。然后我们可以对它们使用半群操作(<>),因为它们现在是同一类型,也是Semigroup

回复更新

Num不是一个类型,它是一个类。 Integer是一种类型,但正如我之前所说,43不是Integer,而是fromInteger 43。它可以是Integer,也可以是任何Num类型。其中一些Num类型可能是Monoid

尝试使用x = mappend (43 :: Integer),您现在发现代码无法编译,因为您强制Num成为Int而不是Monoid x = mappend (43 :: Sum Integer)个实例。

但是,Monoid确实有一个{{1}}实例,所以编译得很好。