(With可能使用GHC扩展),是否有办法减少此类代码中的样板文件?
data Operation = Add | Sub | Mult | Div
data Number
= IntVal Integer
| FloatVal Double
evaluate :: Operation -> Number -> Number -> Number
evaluate op lhs rhs = case op of
Add -> case (lhs, rhs) of
(IntVal i, IntVal j) -> IntVal $ i + j
(FloatVal x, FloatVal y) -> FloatVal $ x + y
_ -> undefined
Sub -> case (lhs, rhs) of
(IntVal i, IntVal j) -> IntVal $ i - j
(FloatVal x, FloatVal y) -> FloatVal $ x - y
_ -> undefined
Mult -> case (lhs, rhs) of
(IntVal i, IntVal j) -> IntVal $ i * j
(FloatVal x, FloatVal y) -> FloatVal $ x * y
_ -> undefined
派生instance Num Number
也会遇到同样的问题。
4条答案
按热度按时间uubf1zoe1#
如果你只是想减少相似模式匹配的样本,那么标准策略就可以了,创建一个helper函数来做重复的事情,并把变化的比特提取到参数中:
我添加了
deriving Show
,这样您就可以看到它在ghci中工作:如果需要,您可以再次应用相同的策略来消除对
liftIntFloatBinOp
的重复调用(尽管使用不那么冗长的名称,它们也不会那么重要),方法是实现如下内容:您可能希望使用一些花哨的语句,例如使用
{-# LANGUAGE RankNTypes #-}
来编写:这在一定程度上是有效的。你可以用它来尝试:
但是当你想除法的时候就失败了:
它失败的原因很简单,如果你继续使用你原来的样板版本,你自己也会注意到:没有一个除法运算符可以同时作用于整数和浮点数,所以没有一个多态函数可以传递给
Number
可能包含的任何一种类型,即使你使用RankNTypes
来传递一个“仍然多态”的参数函数。所以老实说,低技术含量的辅助函数方法可能更好。
omvjsjqw2#
在此示例中,您可以只对结构重新排序:
g9icjywg3#
您可以先创建泛型函数:
则为:
agxfikkp4#
可以考虑的一个相当原始的替代选择:
重复的次数没有减少到零,但减少了很多。