1

以下は、Integral 値のペアを取り、それらを除算する関数です。

divide_v1 :: Integral a => (a, a) -> a
divide_v1 (m, n) = (m + n) `div` 2

Integral 値のペアを指定して関数を呼び出すと、期待どおりに動作します。

divide_v1 (1, 3)

偉大な。私の数値が常に整数であれば、それは完璧です。

Fractional 値のペアを取り、それらを除算する関数を次に示します。

divide_v2 :: Fractional a => (a, a) -> a
divide_v2 (m, n) = (m + n) / 2

Fractional 値のペアを指定して関数を呼び出すと、期待どおりに動作します。

divide_v2 (1.0, 3.0)

偉大な。私の数値が常に分数である場合、それは完璧です。

数値が整数であるか分数であるかに関係なく機能する関数が必要です。

divide_v3 :: Num a => (a, a) -> a
divide_v3 (m, n) = (m + n) ___ 2

_にはどの演算子を使用しますか?

4

2 に答える 2

4

AndrewC の発言を拡張すると、div には / と同じプロパティがありません。たとえば、数学では、a を b = c で割ると、c かける b == a となります。Double や Float などの型を操作する場合、演算 / および * はこのプロパティを満たします (型の精度が許す範囲で)。しかし、Ints で div を使用する場合、このプロパティは当てはまりません。5 div3 = 1 ですが、1*3 /= 5! したがって、さまざまな数値型に対して同じ「除算演算」を使用する場合は、その動作をどのようにするかを考える必要があります。また、誤解を招く可能性があるため、ほぼ確実に同じ演算子 / を使用したくないでしょう。

「除算操作」でオペランドと同じ型を返す場合は、次の 1 つの方法でそれを実現できます。

class Divideable a where
  mydiv :: a -> a -> a

instance Divideable Int where
  mydiv = div

instance Divideable Double where
  mydiv = (/)

GHCi では、次のようになります。

λ> 5 `mydiv` 3 :: Int
1
λ> 5 `mydiv` 3 :: Double
1.6666666666666667
λ> 5.0 `mydiv` 3.0 :: Double
1.6666666666666667

一方、「真の」除算を行いたい場合は、次のように整数型を変換する必要があります。

class Divideable2 a where
  mydiv2 :: a -> a -> Double

instance Divideable2 Int where
  mydiv2 a b = fromIntegral a / fromIntegral b

instance Divideable2 Double where
  mydiv2 = (/)

GHCi では、次のようになります。

λ> 5 `mydiv2` 3
1.6666666666666667
λ> 5.0 `mydiv2` 3.0
1.6666666666666667
于 2012-10-24T13:11:31.337 に答える
1

暗黙の型強制を可能にし、ここで非常にうまく説明されている関連型を探していると思います。以下は、double と integer の加算の例です。

class Add a b where
    type SumTy a b
    add :: a -> b -> SumTy a b

instance Add Integer Double where
    type SumTy Integer Double = Double
    add x y = fromIntegral x + y

instance Add Double Integer where
     type SumTy Double Integer = Double
     add x y = x + fromIntegral y

instance (Num a) => Add a a where
     type SumTy a a = a
     add x y = x + y
于 2012-10-24T11:24:32.527 に答える