AVG in Haskell
haskell で 平均を求める関数を書いてみようと思いったところ、型の制約に四苦八苦。
最初に思いついた関数
avg :: [a] -> a
avg xs = sum xs / length xs
で型のチェックをすると・・・
1 sec2.hs|13 col 19 error| Couldn't match type `a' with `Int'
2 || `a' is a rigid type variable bound by
3 || the type signature for avg :: [a] -> a
4 || at /Users/sec2.hs:13:1
5 || In the return type of a call of `length'
6 || In the second argument of `(/)', namely `length xs'
7 || In the expression: sum xs / length xs
と怒られた・・・
なので早速型を見てみると
(/) :: Fractional a => a -> a -> a
length :: [a] -> Int
sum :: Num a => [a] -> a
みんな型が違うことに気づく・・・
avg :: (Fractional a) => [a] -> a
avg xs = sum xs / fromIntegral (length xs)
と書いて、
ghci> avg [1,2,3]
2.0
ghci>
と値が返ってきたが、何か腑に落ちない。
なのでネットで探すと同じようにはまっている先人を発見
http://stackoverflow.com/questions/2376981/haskell-types-frustrating-a-simple-average-function
ほかにも各クラスやインスタンスの関係があるのか調べてみた。
http://www.sampou.org/haskell/report-revised-j/basic.html
図の6.1に視覚的にクラスとインスタンスの依存関係マップですっきりと理解。