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

jus*_* so 2 haskell operators symbolic-math

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

foo = (3 * 'x' + 2 * 'y' -- => 3x+2y
Run Code Online (Sandbox Code Playgroud)

有没有办法从下面改写实施这样的方式,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'))
Run Code Online (Sandbox Code Playgroud)

丑陋地狱.使用TypeOperators也不会起作用,它需要运算符在其前面:.

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

data Expr = Const Integer
          | Var Char
          | Expr :+: Expr
          | Expr :*: Expr
          | Expr :^: Expr
          | Expr :/: Expr
          deriving (Eq, Show)
Run Code Online (Sandbox Code Playgroud)

表达声明将成为:

foo = (Const 3 :*: Var 'x') :+: (Const 2 :*: Var 'y')
Run Code Online (Sandbox Code Playgroud)

不那么难看,但还是不好.有任何想法吗?

Eri*_*ikR 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
Run Code Online (Sandbox Code Playgroud)