簡體   English   中英

什么樣的'約束'在Haskell中意味着什么

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM