この回答の推奨事項に従ってHaskellの学習を開始しました。だから私は簡単なリスト関数を実装しているだけで、自分では説明できないコンパイラの動作の違いに出くわしました:
-- Impl 1
elementAt :: (Integral b) => [a] -> b -> a
elementAt xs id = xs !! (fromIntegral(id-1))
-- Impl 2
elementAt' :: (Num b) => [a] -> b -> a
elementAt' xs id = xs !! (id-1)
次の署名付き:
fromIntegral :: (Integral a, Num b) => a -> b
(!!) :: [a] -> Int -> a
2 番目の実装でのみエラーが発生しますelementAt'
。
Could not deduce (b ~ Int)
from the context (Num b)
私の理解が正しければ、演算子 (!!) が2 番目の引数としてIntインスタンスを期待していることを意味しますが (署名からわかるように)、提供されたパラメーターがNum型クラスに準拠していることのみを保証します(署名から推測elemenAt'
) 、これはIntよりも広いです。
それを念頭に置いて、最初の実装が実際に機能する理由がわかりません。これもNumfromIntegral
型クラスにのみ準拠する値を返すことを知っています。