2

これが私がやろうとしていることです:

data X = I Int | D Double deriving (Show, Eq, Ord)

{-
-- A normal declaration which works fine
instance Num X where
  (I a) + (I b) = I $ a + b
  (D a) + (D b) = D $ a + b
  -- ...   
-}                                          

coerce :: Num a => X -> X -> (a -> a -> a) -> X
coerce (I a) (I b) op = I $ a `op` b
coerce (D a) (D b) op = D $ a `op` b

instance Num X where
  a + b = coerce a b (+)

コンパイルするとエラーが発生します:

 tc.hs:18:29:
     Couldn't match type `Double' with `Int'
     In the second argument of `($)', namely `a `op` b'
     In the expression: I $ a `op` b
     In an equation for `coerce': coerce (I a) (I b) op = I $ a `op` b

との両方としてcoerce解釈したいのですが。opはタイプなので、これができるはずだと思います。opInt -> Int -> IntDouble -> Double -> DoubleNum a => a -> a -> a

私の主な目標は、機能しているNumサブクラスで必要な繰り返しを抽象化することです。コメントなしのバージョンと同じように記述したいと思います。

4

1 に答える 1

8

強制の定義は、op のタイプをInt -> Int -> Int最初の定義とDouble -> Double -> Double2 番目の定義によって制限します。opそれがすべてのNumクラスで多態的であると本当に言いたい場合はRank2Types、それを機能させるために を使用する必要があります。

coerce :: X -> X -> (forall a . Num a => a -> a -> a) -> X
coerce (I a) (I b) op = I $ a `op` b
coerce (D a) (D b) op = D $ a `op` b
coerce (I a) (D b) op = D $ op (fromIntegral a) b
coerce (D a) (I b) op = D $ op a (fromIntegral b)
于 2012-11-23T04:42:13.123 に答える