2

Haskell で型システムがどのように機能するかを理解しようとしています。

class (Show a) => MyShow a where 
    myShow :: a -> String

instance MyShow Integer where 
    myShow = show 

myshow :: (Show a) => a -> String
myshow = show

main  = do 
    putStrLn $ myshow 1
    putStrLn $ myShow (2 :: Integer) -- why do I need '::Integer' here?

「myshow 1」はタイプなしで機能するのに、「myShow 2」は明示的なタイプなしでエラーを引き起こすのはなぜですか:

Ambiguous type variable `a0' in the constraints:
  (MyShow a0) arising from a use of `myShow'
              at nooverinst.hs:12:16-21
  (Num a0) arising from the literal `2' at nooverinst.hs:12:23
Probable fix: add a type signature that fixes these type variable(s)
In the second argument of `($)', namely `myShow 2'
In the expression: putStrLn $ myShow 2
In the expression:
  do { putStrLn $ myshow 1;
       putStrLn $ myShow 2 }

また奇妙なのは、GHCI を使用するとエラーが発生しないことです。

*Main> myShow 2
"2"

では、この場合の「myshow」と「myShow」の違いは何ですか? どちらも「show」と同じように定義されています。私は何が欠けていますか?

アップデート:

回答の要約: この動作は、デフォルト設定に関係しています。'show 1' と 'myshow 1' が機能するという事実は特殊なケースです (デフォルト設定に関する Haskell レポートのセクションを参照してください)。ソース コードの上に 'default ()' を追加すると、デフォルト設定がオフになり、'myshow 1' でコードが壊れます。したがって、実際には、両方の putStrLn 行の末尾に型シグネチャが必要です。

答えてくれたみんなありがとう!

4

3 に答える 3

9

これは、 http://www.haskell.org/onlinereport/haskell2010/haskellch4.html#x10-790004.3.4で説明されているように、デフォルト設定 (Haskell 標準の暗いコーナーの 1 つ) に関係しています。

要するに、Haskell は数値クラスを特別な方法で扱い、数値クラスで発生するあいまいさを自動的にデフォルト設定しますが、それは関連する他の制約が基底クラスである場合に限られます。そういう意味でShowは、 も特別で、MyShow自分で定義することは別の方法で扱われます。

GHCi では、拡張されたデフォルト ルールが適用され、制限がわずかに緩和されます。これらはhttp://www.haskell.org/ghc/docs/latest/html/users_guide/interactive-evaluation.html#extended-default-rulesで説明されています

于 2012-08-28T21:50:46.923 に答える
4

1 は任意の Num 型を持つことができるため、コンパイラは何らかの手段を使用して何らかの型を選択する必要があります。これはデフォルトで処理されます。ただし、デフォルトは Prelude クラスでのみ発生し、あなたのクラスでは発生しません。Haskell レポートのデフォルトに関するセクションをチェックしてください。すべて詳しく説明されています。

于 2012-08-28T21:53:45.573 に答える
3

いくつかの数値型 ( のインスタンスNum) があり、Haskell は を書いたときにどれを意味するのかわかりません2。ghc/ghci は のような式に対して Integer のようなデフォルトの型を選択するようにプログラムされているため、多くの場合、それを回避できます2+2myshowHaskell は自動的に選択しているインスタンスにShow関連付けられているインスタンスを使用していますが、 .NummyShow

独自の型クラスMyShowは とは関係がNumないため、Haskell はデフォルトのルールを使用して選択することはできません。[申し訳ありませんが、以前のバージョンではこれが間違っていました。]

3などの数値リテラル6.7はオーバーロードされている (複数の型のデータを表すことができる) ため、これは奇妙ですChar

于 2012-08-28T21:38:59.930 に答える