をいじってみるとghci、たまたま式(*) 1 [1..5]が有効な型を持っていることに気付きました。
:t (*) 1 [1..5]
(*) 1 [1..5] :: (Enum t, Num [t], Num t) => [t]
Num [t]どうやらそれは、エラーが発生するように、私には不可能に見えるものを含む、いくつかの型制約を持つリストです。
これはどのように式のタイプですか?ghciここでの:tコマンドがエラーを出さないのはなぜですか?
をいじってみるとghci、たまたま式(*) 1 [1..5]が有効な型を持っていることに気付きました。
:t (*) 1 [1..5]
(*) 1 [1..5] :: (Enum t, Num [t], Num t) => [t]
Num [t]どうやらそれは、エラーが発生するように、私には不可能に見えるものを含む、いくつかの型制約を持つリストです。
これはどのように式のタイプですか?ghciここでの:tコマンドがエラーを出さないのはなぜですか?
Num [t]可能であるだけでなく、簡単です:
import Control.Applicative
liftA0 = pure -- hobgoblins, simple minds, etc.
liftA1 = fmap
instance Num t => Num [t] where
(+) = liftA2 (+)
(-) = liftA2 (-)
(*) = liftA2 (*)
negate = liftA1 negate
abs = liftA1 abs
signum = liftA1 signum
fromInteger n = liftA0 (fromInteger n)
したがって、式が適切なインスタンスで適切に型付けされていると推測する代わりに、GHC がエラーを生成するのはひどいことです。
もちろん、このインスタンスを実際のコードで書くのもひどいことですが、GHC は、私たち人間のようにコードを判断する仕事をすべきではありません。
型を説明するために、これらの制約がどのようになるかを見てみましょう。
Haskell では、数値リテラルは への呼び出しに置き換えられますfromInteger(またはfromRational、小数点または 'e' が含まれる場合)。このようにして、'1' を書き込んで、float、double、int などを指定できます。のタイプfromIntegerは
fromInteger :: Num a => a
だから、型を持っている1脱糖を取得しますfromInteger (1::Integer)Num t => t
Haskell では、構文[a..b]は呼び出しに変換されenumFromTo a b、型はenumFromTo :: Enum a => a -> a -> [a]. これらをまとめると、
[1..5] == enumFromTo (fromInteger 1) (fromInteger 5) :: (Enum a, Num a) => [a]
の型(*)が にNum b => b -> b -> bなったので、これらをすべて組み合わせて次のようにします。
(Num t,
Num a,
Enum a,
Num b,
t~b,
[a]~b) => b
とは同じa~b種類を意味することに注意してください。これらを組み合わせると、タイプが得られますab
(Num a, Enum a, Num [a]) => [a]