7

矢印とその矢印を説明する文字列を保持するタプルを作成したいと思います。(矢印の代わりに)関数を使用してこれを行うと、次のように機能します。

funTimes10 = (*10)
describe10 = "times 10"

tuple10 :: (Num b) => ((b -> b), String)
tuple10 = (,) funTimes10 describe10

fstで関数にアクセスでき、関数sndの説明文字列を取得できます。

ただし、次のように、関数を矢印で交換すると、次のようになります。

aTuple10 :: (Arrow a, Num b) => (a b b, String)
aTuple10 = (,) (arr funTimes10) describe10
  • fstまだ動作し、私の矢印を返しますが、
  • が付いた説明文字列がありませんsnd

私はこのエラーメッセージだけを受け取りました:

Ambiguous type variable `a0' in the constraint:
  (Arrow a0) arising from a use of `aTuple10'
Probable fix: add a type signature that fixes these type variable(s)
In the first argument of `snd', namely `aTuple10'
In the expression: (snd aTuple10)
In an equation for `it': it = (snd aTuple10)

なぜこのエラーが発生するのですか?それを回避するにはどうすればよいですか?

4

2 に答える 2

9

次のタイプを見てみましょうsnd

snd :: (foo, x) -> x

(わかりやすくするために型変数の名前を変更しました)

fooタイプが示すのは、タイプと、を持つタプルの場合、タイプxの何かを返すということですx。ここで知っておくべき重要なことは、バリューシステムが別名であるということです。Haskellのランタイムは怠惰であり、Haskellの型システムは厳密です。つまり、との両方の型を呼び出す前に知っfooxおく必要がありますsnd

最初のケースでは、が存在する場合、具体的な型についてはどこにも言及していないためNum b => (b -> b, String)、呼び出しsndはあいまいなままになります。また、。とは異なるため、return型から推測することはできません。言い換えると、任意の数値タイプのタプルである可能性があり、タイプチェッカーはどれを判別できないため、あいまいです。ここでの秘訣は、Haskellのデフォルトのルールを開始することです。このルールでは、数値の型があいまいな場合は、デフォルトで。に設定する必要があります。で警告をオンにした場合は、これが発生していると表示されます。したがって、私たちのタイプはになり、呼び出すことができます。bfoo ~ bx(b, b)Integer-Wall(Integer -> Integer, String)snd

ただし、2番目のケースでは、bデフォルトのルールを使用して推測することができますが、のデフォルトがないArrowためa、行き詰まります。続行するには、必要な矢印を明示的に指定する必要があります。aTuple10これは、最初に別の場所の値を使用して行うことができます。

let bla = aTuple10  -- We do this because `aTuple10` can have type variables, but `bla` cannot (by default)
fst bla (23 :: Int) -- This fixes the type of `bla`, so that `a ~ (->)` and `b ~ Int`
print $ snd bla     -- So the arrow isn't ambiguous here

...または、必要なタイプを指定することもできます。

print $ snd (aTuple10 :: (Int -> Int, String))

PSあいまいな数値のデフォルトのタイプを変更したい場合は、defaultキーワードが役立ちます。

于 2012-02-27T13:59:03.423 に答える
-1

私はこれをコンパイルしようとしました:

import Control.Arrow

funTimes10 = (*10)
describe10 = "times 10"

tuple10 :: (Num b) => ((b -> b), String)
tuple10 = (,) funTimes10 describe10

aTuple10 :: (Arrow a, Num b) => (a b b, String)
aTuple10 = (,) (arr funTimes10) describe10

しかし、私はこれを取得します:

Could not deduce (b ~ Integer)
from the context (Arrow a, Num b)
  bound by the type signature for
             aTuple10 :: (Arrow a, Num b) => (a b b, String)
  at D:\dev\haskell\arr_tuple.hs:10:1-42
  `b' is a rigid type variable bound by
      the type signature for
        aTuple10 :: (Arrow a, Num b) => (a b b, String)
      at D:\dev\haskell\arr_tuple.hs:10:1
Expected type: b -> b
  Actual type: Integer -> Integer
In the first argument of `arr', namely `funTimes10'
In the first argument of `(,)', namely `(arr funTimes10)'

したがって、使用する矢印インスタンスを決定する必要があると思います。arr funTimesつまり、アノテーションを使用しての具体的なタイプを指定する必要がある場合があります。

于 2012-02-27T13:59:25.050 に答える