0

私は自分の言語のインタープリターを書いていますが、このタイプの抽象構文ツリーがあります。

data Expression = 
  PInt Int
  | PFloat Double
  | PString String
  | PChar Char
  | PBool Bool
  | Var String
  | Unbound String String
  | Unary String Expression
  | Binary String Expression Expression
  | Call Expression [Expression]
  | Lambda Expression
  | Assign String Expression Expression
  | Conditional Expression Expression Expression
  deriving Eq

数値演算に既存の機械を使用できるように、クラスの Num のインスタンスを作成しようとしています。ここに私が書いたものがあります:

instance Num Expression where
   PInt a + PInt b = PInt $ a + b
   PInt a + PFloat b = PFloat $ a + b
   PFloat a + PInt b = PFloat $ a + b
   PFloat a + PFloat b = PFloat $ a + b
   _ + _ = undefined
   PInt a - PInt b = PInt $ a - b
   PInt a - PFloat b = PFloat $ a - b
   PFloat a - PInt b = PFloat $ a - b
   PFloat a - PFloat b = PFloat $ a - b
   _ - _ = undefined
   PInt a * PInt b = PInt $ a * b
   PInt a * PFloat b = PFloat $ a * b
   PFloat a * PInt b = PFloat $ a * b
   PFloat a * PFloat b = PFloat $ a * b
   _ * _ = undefined
   negate (PInt a) = PInt (-a)
   negate (PFloat a) = PFloat (-a)
   negate _ = undefined
   abs (PInt a) = PInt $ abs a
   abs (PFloat a) = PFloat $ abs a
   abs _ = undefined
   signum (PInt a) = PInt $ signum a
   signum (PFloat a) = PFloat $ signum a
   signum _ = undefined
   fromInteger i = (PInt $ fromInteger i)

これにより、特に int と float を組み合わせた場所でエラーが発生します。

Prelude> :load AST.hs
[1 of 1] Compiling AST          ( AST.hs, interpreted )

AST.hs:38:36:
    Couldn't match expected type `Double' with actual type `Int'
    In the first argument of `(+)', namely `a'
    In the first argument of `PFloat', namely `(a + b)'
    In the expression: PFloat (a + b)

AST.hs:39:37:
    Couldn't match expected type `Double' with actual type `Int'
    In the second argument of `(+)', namely `b'
    In the second argument of `($)', namely `a + b'
    In the expression: PFloat $ a + b

AST.hs:43:33:
    Couldn't match expected type `Double' with actual type `Int'
    In the first argument of `(-)', namely `a'
    In the second argument of `($)', namely `a - b'
    In the expression: PFloat $ a - b

AST.hs:44:37:
    Couldn't match expected type `Double' with actual type `Int'
    In the second argument of `(-)', namely `b'
    In the second argument of `($)', namely `a - b'
    In the expression: PFloat $ a - b

AST.hs:48:33:
    Couldn't match expected type `Double' with actual type `Int'
    In the first argument of `(*)', namely `a'
    In the second argument of `($)', namely `a * b'
    In the expression: PFloat $ a * b

AST.hs:49:37:
    Couldn't match expected type `Double' with actual type `Int'
    In the second argument of `(*)', namely `b'
    In the second argument of `($)', namely `a * b'
    In the expression: PFloat $ a * b
Failed, modules loaded: none.

Haskell の Int + Double の型は Double であるため、これは私には意味がありません。したがって、a + b は Double に解決される必要があり、PFloat のコンストラクターは Double を取るため、問題ありません...なぜそうではありませんか?

解決済み:fromIntegralタイプの変数の前で使用すると、問題がInt修正されます。

4

1 に答える 1

3

Num 型クラスの算術演算子は、両方の引数が同じ型を持つことを想定しているため、fromIntegralそれらを加算する前に、Int を Double を使用して変換する必要があります。

たとえば、これを置き換えます

PInt a + PFloat b = PFloat $ a + b

これとともに

PInt a + PFloat b = PFloat $ fromIntegral a + b
于 2013-08-14T22:02:30.110 に答える