[英]Why doesn't this average function in haskell work?
我想在Haskell中創建一個簡單的平均(平均)函數,所以我在ghci中嘗試了以下內容:
ghci> let avg xs = (sum xs) / (length xs)
它會引發以下錯誤:
No instance for (Fractional Int)
arising from a use of `/'
Possible fix: add an instance declaration for (Fractional Int)
In the expression: (sum xs) / (length xs)
In an equation for `avg': avg xs = (sum xs) / (length xs)
所以,我決定通過嘗試以下方法將其分解:
ghci> let a = (sum [1,2])
ghci> let b = (length [1,2])
這一切都很好。
那么我嘗試了以下內容
ghci> a/b
我收到以下錯誤:
Couldn't match expected type `Integer' with actual type `Int'
In the second argument of `(/)', namely `b'
In the expression: a / b
In an equation for `it': it = a / b
那么,在Haskell中Integer
和Int
不同? - 如果是這樣,我怎樣才能使原始功能起作用?
問題是
length :: [a] -> Int
但
(/) :: (Fractional a) => a -> a -> a
所以,當你說whatever / length xs
,它不會輸入,因為Int不是分數數字類型! 這就是“No instance for ...”錯誤試圖告訴你的。 這個定義可行:
GHCi> let avg xs = sum xs / fromIntegral (length xs)
這里,我們使用fromIntegral :: (Integral a, Num b) => a -> b
將我們從length
得到的Int轉換為小數。 請注意,由此產生的函數僅適用於小數的列表(但例如avg [1,2,3]
仍然可以正常工作)。
為了解釋你在“分片”中所做的錯誤,這是因為在let a = sum [1,2]
,列表的元素是整數,所以它們的和是一個整數,但是在let b = length [1,2]
,根據我在上面顯示的length
類型,得到的長度是一個Int。 因此,當你執行a/b
,這會失敗,直到它意識到Int和Integer不是Fractional的實例 - 因為(/)
接受兩個相同類型的參數,它不可能工作。
是的,Integer和Int是不同的 - Int是一個固定精度的整數類型,通常是數字的大小,就像C中的long
一樣,而Integer是一個任意精度的bignum,能夠存儲任何整數; 或者至少,任何適合你的RAM的整數:)
另一種可能的方法是使用Data.List.genericLength
將avg xs
定義為sum xs / genericLength xs
,它可以使用任何數字類型,而不僅僅是Ints:
genericLength :: (Num b) => [a] -> b
為此,您必須在GHCi中import Data.List
。 另一種可能的方法(但一個導致完全不同的功能)將是使用整數除法: let avg xs = sum xs `div` length xs
(注意: a `div` b
只是div ab
;這個句法糖用於每個功能)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.