它如何成为特定类型?

zer*_*ing 0 haskell

我有以下代码片段:

Prelude Data.Monoid> :t 1 <> (2 :: Sum Integer)
1 <> (2 :: Sum Integer) :: Sum Integer
Run Code Online (Sandbox Code Playgroud)

怎么1变成Sum Integer打字?

更新

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

Prelude Data.Monoid> x = mappend 43
Run Code Online (Sandbox Code Playgroud)

为什么mappend会接受这个号码4343是一个Num类型,它没有monoid实例.

Cli*_*ton 5

首先(2 :: Sum Integer).

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

(2 :: Sum Integer) == ((fromInteger (2 :: Integer)) :: Sum Integer) 
Run Code Online (Sandbox Code Playgroud)

Haskell只允许左侧的符号,因此更容易键入,但它相当于右侧的代码.

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

fromInteger :: Num a => Integer -> a
Run Code Online (Sandbox Code Playgroud)

因此,(fromInteger (2 :: Integer))具有类型Num a => a

在库中的某个位置,您将拥有如下所示的实例:

instance Num a => Num (Sum a) where ...
Run Code Online (Sandbox Code Playgroud)

由于Integer是一个Num,所以是Sum Integer.

因此,我们可以转换Num a => aSum Integer代刚a = Sum Integer.

最后,我们有这个Semigroup功能:

(<>):: Semigroup a => a - > a - > a

还有一个例子:

instance Num a => Semigroup (Sum a) where ...
Run Code Online (Sandbox Code Playgroud)

在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实例,所以应该编译好.