下面的简化函数试图简化类型
的数学表达式
((2 + 3) * (2 + 4))
到
(2 * (3 + 4))
。
理想情况下,我想将匹配表达式写为:
| Product (Sum (c, a), Sum (c, b)) -> Product (c, Sum (a, b))
但是这给了我" c在这个模式中绑定两次"错误。所以我采取了守卫条件。
我想知道是否有更好的方法可以使用Active Patterns实现这一目标?
type Expr =
| Number of int
| Sum of Expr * Expr
| Product of Expr * Expr
let rec eval =
function
| Number n -> n
| Sum (l, r) -> eval l + eval r
| Product (l, r) -> eval l * eval r
let rec show =
function
| Number n -> n.ToString()
| Sum (l, r) -> "(" + show l + " + " + show r + ")"
| Product (l, r) -> "(" + show l + " * " + show r + ")"
let rec simplify =
function
| Product (Sum (c, a), Sum (d, b)) when (c = d) -> Product (c, Sum (a, b))
| Sum (l, r) -> Sum (simplify l, simplify r)
| Product (l, r) -> Product (simplify l, simplify r)
| e -> e
let c = Product (Sum (Number 2, Number 3), Sum (Number 2, Number 4))
show c
eval c
show (simplify c)
答案 0 :(得分:3)
我不确定活动模式是否更好,但它们在匹配语句中可以更具说明性,允许您分解每种情况。
这是一个使用活动模式的版本,我也在逻辑中做了修复。请注意它是多么冗长:
type Expr =
| Number of int
| Sum of Expr * Expr
| Product of Expr * Expr
let rec eval =
function
| Number n -> n
| Sum (l, r) -> eval l + eval r
| Product (l, r) -> eval l * eval r
let rec show =
function
| Number n -> n.ToString()
| Sum (l, r) -> "(" + show l + " + " + show r + ")"
| Product (l, r) -> "(" + show l + " * " + show r + ")"
let (|CommonFactor|_|) =
function
| Sum (Product (a, b), Product (c, d)) when (a = c) -> Some <| Product (a, Sum (b, d))
| Sum (Product (a, b), Product (c, d)) when (a = d) -> Some <| Product (a, Sum (b, c))
| Sum (Product (a, b), Product (c, d)) when (b = c) -> Some <| Product (b, Sum (a, d))
| Sum (Product (a, b), Product (c, d)) when (b = d) -> Some <| Product (b, Sum (a, c))
| _ -> None
let (|Operation|_|) simplify =
function
| Sum (l, r) -> Some <| Sum (simplify l, simplify r)
| Product (l, r) -> Some <| Product (simplify l, simplify r)
| _ -> None
let (|Constant|_|) =
function
| Number _ as n -> Some n
| _ -> None
let rec simplify =
function
| CommonFactor exp -> simplify exp
| Operation simplify exp -> exp
| Constant exp -> exp
| _ -> failwith "Oh teh noes!"
let c = Sum (Product (Number 2, Number 3), Product (Number 2, Number 4))
show c |> Dump
eval c |> Dump
show (simplify c) |> Dump