![](/img/trans.png)
[英]What Does Kind Constraint mean in Haskell typeclass instance?
[英]What does has kind 'Constraint' mean in Haskell
我對Haskell很新鮮,我試圖通過編寫一些代碼來理解語言。 我只熟悉關於ghci的非常簡單的指令:head,tail,sum,(*)等 - 非常簡單。
我試圖做的功能是解決畢達哥拉斯定理任意維數的向量。 這看起來像這樣:平方根(a ^ 2 + b ^ 2 + c ^ 2 ...)
我在ghci中可以做幾行,我試圖做一個函數如下:
sq x = x*x
b = map sq [1,2,3]
a = sum b
x = sqrt b
當我這樣做時,我嘗試包含許多種類的簽名,目前我的函數看起來像這樣:
mod :: [Num a] => a
mod x = sqrt a
where a = sum [b]
where [b] = map sq [x]
我嘗試運行它時,我不明白這個問題:
Expected a constraint, but ‘[Num a]’ has kind ‘*’
• In the type signature:
Main.mod :: [Num a] => a
一些要調整的事情:
0) mod
不是函數的好名稱,因為它是標准庫中模數函數的名稱。 我會稱它為norm
。
1)您打算寫的類型簽名是:
norm :: Num a => [a] -> a
[a]
是具有類型的元素列表的類型a
。 =>
之前的Num a
不是類型,而是約束 ,它指定a
必須是數字類型(或者更確切地說,它必須是Num
類的實例)。 [Num a] =>
導致您看到的錯誤,因為給定方括號,類型檢查器將其視為嘗試使用列表類型而不是約束。
除了Num a
問題,你已經從簽名中省略了結果類型。 更正的簽名反映了您的函數采用數字列表並返回一個數字。
2) Num a
約束對於你想要做的事情來說太弱了。 為了使用sqrt
,你需要的不僅僅是一個數字類型,而是一個Floating
的實例(參見leftaroundabout對這個答案的評論):
GHCi> :t sqrt
sqrt :: Floating a => a -> a
因此,您的簽名應該是
norm :: Floating a => [a] -> a
3) [x]
是具有單個元素x
的列表。 如果您的參數已經是一個列表,正如類型簽名所示,則無需將其括在方括號中。 那么你的功能就變成了:
norm :: Floating a => [a] -> a
norm x = sqrt a
where a = sum b
where b = map sq x
或者,更整潔,沒有第二個where
-block:
norm :: Floating a => [a] -> a
norm x = sqrt (sum b)
where b = map sq x
如您所知,可以按類型對值進行分類。 "foo"
類型為[Char]
, Just 'c'
類型為Maybe Char
等。
類似地,類型可以按其種類分類。 您可以提供值的所有具體類型都有類型*
。 你可以在GHCi中使用:k
命令看到這個:
> :k Int
Int :: *
> :k Maybe Int
Maybe Int :: *
類型構造函數也有種類。 它們本質上是類型值函數,因此它們的類型與常規函數類似。
> :t id
id :: a -> a
> :k Maybe
Maybe :: * -> *
但是Num a
什么? 它不是一種類型,所以沒有類型*
。 它不是類型構造函數,因此它沒有箭頭類型。 它是新的東西,所以創造了一種新的形式來描述它。
> :k Num Int
Num Int :: Constraint
Num
本身是一個Constraint
valued函數:它需要一個類型的值*
並產生一個Constraint
:
> :k Num
Num :: * -> Constraint
具有類型Constraint
的東西用於指定特定類型必須是其實例的類型類。 它是在類型簽名中=>
之前可能出現的值。 它也是instance
“函數”的“參數”:
instance Num Int where
...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.