在Haskell中编写数学表达式的惯用法

时间:2014-12-20 22:48:35

标签: haskell operators symbolic-math

我想用Haskell写下数学表达式。 例如:

foo = (3 * 'x' + 2 * 'y' -- => 3x+2y

有没有办法从下面重写实现,AddMul可以分别由运算符+*替换?

data Expr = Const Integer
          | Var Char
          | Add Expr Expr
          | Mul Expr Expr
          deriving (Show)
 ...
 foo =  Add (Mul (Const 3)  (Var 'x')) (Mul (Const 3) (Var 'y'))

丑陋地狱。 使用TypeOperators也不会起作用,它要求运算符前面加:

infixl 4 :+:
infixl 5 :*:, :/:
infixr 6 :^:

data Expr = Const Integer
          | Var Char
          | Expr :+: Expr
          | Expr :*: Expr
          | Expr :^: Expr
          | Expr :/: Expr
          deriving (Eq, Show)

表达声明将成为:

foo = (Const 3 :*: Var 'x') :+: (Const 2 :*: Var 'y')

不那么难看,但仍然很糟糕。有什么想法吗?

2 个答案:

答案 0 :(得分:7)

{-# LANGUAGE OverloadedStrings #-}

import Data.String

data Expr = Const Integer
          | Var Char
          | Add Expr Expr
          | Mul Expr Expr
          deriving (Show)

instance Num Expr where
  (+) = Add
  (*) = Mul
  fromInteger = Const
  abs = undefined
  signum = undefined
  negate = undefined

instance IsString Expr where
  fromString s = Var (head s)

main = do
  let expr = 3 * "x" + 2 * "y" :: Expr
  print expr

答案 1 :(得分:4)

您可以为表达式数据类型创建Num / Real实例。

instance Num Expr where
    a + b = Add a b
    a * b = Mul a b
    fromIntegral a = Const a

x = Var 'x'
y = Var 'y'

result = 2 * x + 3 * y