在Haskell中键入签名

lab*_*nth 3 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)
Run Code Online (Sandbox Code Playgroud)

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

vMult :: (Num a) => Vector a -> Num -> Vector a  
Run Code Online (Sandbox Code Playgroud)

我的理解是,既然m是类型Num(例如,数量8),由于i, j, kNum为好,应该与计算没有问题Vector (i*m) (j*m) (k*m).

请理解我的理解.

And*_*ewC 6

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

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

vMult :: (Num a) => Vector a -> a -> Vector a
Run Code Online (Sandbox Code Playgroud)

意思是"只要a是一个数字类型,vMult取一个as和一个单一a的向量并返回一个as 的向量."

这意味着vMult可以像
vMult :: Vector Int -> Int -> Vector Int或那样工作
vMult :: Vector Double -> Double -> Vector Double.
请注意,通过a使用单个数字类型替换原始中的所有s来获取每种类型.

Num 它本身没有意义

Num 单独表示"是一个数字类型",所以如果你的函数有类型签名

vMult :: (Num a) => Vector a -> Num -> Vector a
Run Code Online (Sandbox Code Playgroud)

它会读作"只要a是一个数字类型,vMult需要一个矢量as和一个数字类型并返回一个矢量as".它在英语中是不合语法的,就像它在Haskell中的错误一样.

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

事实不是类型

你也不能使用Num a而不是a喜欢,Vector a -> Num a -> Vector a因为你不能把断言放在你需要名词的地方:"给我你的钥匙圈,钥匙是用金属制成的,所以我可以给你一个新的钥匙圈".