15

Haskell の型システムについてかなり一般的な質問があります。私はそれに慣れようとしていますが、次の機能があります。

getN :: Num a => a
getN = 5.0 :: Double

これをコンパイルしようとすると、次のエラーが発生します。

Couldn't match expected type `a' against inferred type `Double'
  `a' is a rigid type variable bound by
      the type signature for `getN' at Perlin.hs:15:12
In the expression: 5.0 :: Double
In the definition of `getN': getN = 5.0 :: Double

私がこれを理解しているように、関数はクラス Num の型を「返す」ように設定されています。Double はこのクラス ( http://www.zvon.org/other/haskell/Outputprelude/Num_c.html ) に含まれているため、この場合は Double を「返して」も問題ないと思っていました。

誰かがこれを説明できますか?

4

3 に答える 3

16

シグネチャを持つ関数は、クラス内の任意のNum a => a型に対して機能することが期待されています。実装は、クラスのすべての型ではなく、1 つの型に対してのみ機能するため、コンパイラは文句を言います。Num5.0 :: Double

一般的な関数の例は次のとおりです。

square :: (Num a) => a -> a
square x = x * x

これはNum . double、整数、および使用したいその他の数値に対して機能します。そのため、パラメーターが class にあることだけを要求するジェネリック型シグネチャを持つことができますNum。(関数はそこで定義されている とNumの乗算を使用するため、型クラスが必要です)*

于 2009-10-07T21:25:23.337 に答える
9

sth の回答に追加するには: Haskell はオブジェクト指向ではありません。Doubleが のサブクラスであるというのは正しくないため、たとえば Java でできるように、ポリモーフィックな値を返すと約束している場合はNum、 a を返すことはできません。DoubleNum

書くときは、制約getN :: Num a => a内で完全に多様な値を返すことを約束します。これは事実上、 、、などNumの型クラスの関数のみを使用できることを意味します。Num+*-fromInteger

于 2009-10-08T08:48:41.727 に答える
3

存在記号型をチェックしてください。

これを解決する1つの方法は、新しいデータ型を定義することです。

data NumBox = forall n. Num n => NumBox n

これを機能させる必要があります-XExistentialQuantification

今、あなたは次のようなものを書くことができます

getN :: NumBox
getN = NumBox (5.0 :: Double)

NumBox-listを次のように定義することもできます

let n3 = [NumBox (4.0 :: Double), NumBox (1 :: Integer), NumBox (1 :: Int) ]
于 2009-10-12T09:10:37.473 に答える