使用{{3}}库 编写抽象语法树和相应的表达式赋值器很容易:
PING 109.236.87.141 (109.236.87.141): 56 data bytes
ping: sending packet: Network is unreachable
现在看一下{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE LambdaCase #-}
import Data.Functor.Foldable
import Data.Functor.Foldable.TH
data Expr = Plus Expr Expr
| Mult Expr Expr
| Const Expr
deriving (Show, Eq)
makeBaseFunctor ''Expr
-- Write a simple evaluator
eval :: Expr -> Int
eval = cata alg
where
alg = \case
PlusF x y -> (+) x y
MultF x y -> (*) x y
ConstF x -> x
的where子句中alg
函数的情况。我认为所有eval
和x
变量
不应该是必要的。因此,我正在寻找某种方式(语法,语言扩展等)
删除此样板并只写:
y
答案 0 :(得分:3)
https://hackage.haskell.org/package/catamorphism-0.5.1.0/docs/Data-Morphism-Cata.html导致ExprF
的变形。
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE TemplateHaskell #-}
import Data.Functor.Foldable
import Data.Functor.Foldable.TH
import Data.Morphism.Cata
data Expr
= Plus Expr Expr
| Mult Expr Expr
| Const Expr
deriving (Show, Eq)
makeBaseFunctor ''Expr
$(makeCata defaultOptions ''ExprF)
-- Write a simple evaluator
eval :: Expr -> Int
eval = cata $ exprF (+) (*) id
请注意,它还可以为Expr
派生一个catamorphism,产生eval = expr (+) (*) id
并让您跳过Data.Functor.Foldable.TH
这个特定的用例。
答案 1 :(得分:1)
或者,您可以重构您的语言,一方面进行二元操作,另一方面进行一元化操作。你写的是:
data BinOp = PlusOp | MultOp deriving (Show, Eq)
data UnOp = ConstOp deriving (Show, Eq)
data Expr = Bin BinOp Expr Expr
| Un UnOp Expr
deriving (Show, Eq)
makeBaseFunctor ''Expr
评估员随后成为:
eval :: Expr -> Int
eval = cata $ \case
BinF op l r -> bin op l r
UnF op v -> un op v
where
bin = \case
PlusOp -> (+)
MultOp -> (*)
un = \case
ConstOp -> id