繁体   English   中英

在Haskell中键入签名

[英]Type Signatures in Haskell

我的问题是关于类型签名。

以下代码符合:

data Vector a = Vector a a a deriving (Show) 
vMult :: (Num a) => Vector a -> a -> Vector a 
(Vector i j k) `vMult` m = Vector (i*m) (j*m) (k*m)

不过,我不明白为什么有以下不起作用取代上述类型签名(上2号线):

vMult :: (Num a) => Vector a -> Num -> Vector a  

我的理解是因为mNum类型(例如数字8 ),并且因为i, j, k也是Num ,所以计算Vector (i*m) (j*m) (k*m)应该没有问题Vector (i*m) (j*m) (k*m)

请理解我的理解。

Num a实际上根本不是一种类型

Num是一个类型类,所以如果我说Num a它意味着a是一个数字类型,那么

vMult :: (Num a) => Vector a -> a -> Vector a

装置“只要a是一个数字型, vMult采用的矢量a S和一个单一的a ,并返回的向量a秒。”

这意味着vMult可以像
vMult :: Vector Int -> Int -> Vector Int
vMult :: Vector Double -> Double -> Vector Double
请注意您更换所有的得到每种类型的a有一个单一的数字型在原有秒。

Num就自己没有意义

Num本身就意味着“是一个数字类型”,所以如果你的函数有类型签名

vMult :: (Num a) => Vector a -> Num -> Vector a

它将读“只要a是一个数字型, vMult采用的矢量a S和一个是一个数字型和返回的向量a秒。” 它在英语中是不合语法的,就像它在Haskell中的错误一样。

这就像是说“给我一些黄油,有一个锋利的边缘”,而不是“给我一些黄油和一把刀”。 有效的类型签名就像是说“找到你可以传播的东西(称之为k),并给我一些黄油和k。”

事实不是类型

你也不能使用Num a ,而不是aVector a -> Num a -> Vector a ,因为你需要一个名词,你不能把一个断言:“给我你的钥匙圈和钥匙由金属制成,以便我可以给你一个新的钥匙圈“。

乘法是在Num aNum a上定义的,即属于Num Typeclass的相同Type的2个参数。

(*) :: (Num a) => a -> a -> a 

如果您的类型签名中只有Num ,则类似于要求允许在IntegerFloat之间进行乘法,因为两者都是属于Typeclass Num类型。 这就是为什么你需要指定应该使用的Type而不仅仅是Typeclass

当你将它用于Vector时,已经有一个约束来确保a应该属于Num 为了将Vector每个元素与所选的标量相乘,该标量不仅必须属于Num ,还必须是相同的类型,即a

Num不是可以在那里使用的具体类型 它是一个一元类型的构造函数 ,必须专门使用另一种类型。 用OOP术语来说, Num不是一个类似OOP的抽象“超类”类型,而是一个必须专门用于它的工厂。

因此,尝试将Num传递到需要类型的地方(类型的“类型”) *就像尝试传递一个函数( :: a -> b ),其中需要一个值( :: c )(区别在于前者是在类型级别完成的):

ghci> :kind Int
Int :: *

ghci> :kind Num
Num :: * -> Constraint

所以我们可以看到该应用程序Num于任何类型的一种*在类型检查的时候会产生一种ConstraintConstraint可能只有之前使用=>在类型签名(限制什么类型在位置正确aVector a -> a -> Vector a ,这就是Constraint的意思)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM