型の制約が型エイリアスでどのように機能するかを理解しようとしています。RankN型の別名混乱のタイプ
type NumList a = Num a => [a]
そして、私は次の機能があります:
addFirst :: a -> NumList a -> NumList
addFirst x (y:_) = x + y
この関数は、次のエラーで失敗します。
Type.hs:9:13: error:
• No instance for (Num a) arising from a pattern
Possible fix:
add (Num a) to the context of
the type signature for:
addFirst :: a -> NumList a -> a
• In the pattern: y : _
In an equation for ‘addFirst’: ad
明らかであるまずは、私は次のタイプの別名を持っていると仮定しましょう。この問題は、すでにここで説明:
Understanding a rank 2 type alias with a class constraint
そして、私たちが動作するように、前の例では動作しません。なぜ、このようなタイプの別名のため{-# LANGUAGE RankNTypes #-}
を必要とする理由私は理解しています。次の例は、(GHC 8に)罰金コンパイルしかし、なぜ私が理解していないことです。もちろん
prepend :: a -> NumList a -> NumList a
prepend = (:)
私は間違った値を渡ししようとした場合、それはghci
に失敗:
λ: prepend 1 []
[1]
λ: prepend "xx" []
<interactive>:3:1: error:
• No instance for (Num [Char]) arising from a use of ‘prepend’
• When instantiating ‘it’, initially inferred to have
this overly-general type:
NumList [Char]
NB: This instantiation can be caused by the monomorphism restriction.
はタイプのように思えます
first :: NumList a -> a
first = head
:実行時に遅れ:(
また、いくつかの簡単な、コードの同じ部分であるように思わはコンパイルされません型チェック
そして、次のエラーが発生します。
Type.hs:12:9: error:
• No instance for (Num a)
Possible fix:
add (Num a) to the context of
the type signature for:
first :: NumList a -> a
• In the expression: head
In an equation for ‘first’: first = head
誰かがここで何が起こっているか説明できますか?私は機能の種類のチェックの有無にある程度の一貫性があると思います。
'Num a => a'を関数' NumDict a - > a 'と考えると、それはすべて明らかでなければなりません。 –
@Alecが提案した質問に既にリンクしていましたが、2番目の答え(luquiによるもの)が受け入れられているものよりもおそらくもっと明確であることを指摘する価値があります。なぜ 'prepend'が動作し、 (要するに、コンパイラは、シノニムが署名の最も右の位置にある場合、コンパイラはその制約をあなたが望むところに移動することができます)。ちなみに、 'prepend'の使用例には、' Num a => a - > [a] - > [a] '関数が期待しているものと全く同じように、奇妙なものや遅延したものはありませんする。 – duplode
はい、リンクされた質問に対するluquiの答えは正確に関連しています。 –