Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell中的多态性评估器_Haskell - Fatal编程技术网

Haskell中的多态性评估器

Haskell中的多态性评估器,haskell,Haskell,我如何编辑下面的代码,使我没有那么多的求值器(它们现在反映了各种结果类型)?我想要一个单独的评估者,这样我就不会事先知道结果的类型。我想要一个语言评估员。我是否需要为Exp添加值类型才能执行此操作?这看起来怎么样?什么样的值类型以及如何编辑当前的eval函数以反映这种新的多态类型 {-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-} data Exp = V Var | B Bool | MyInt Int |

我如何编辑下面的代码,使我没有那么多的求值器(它们现在反映了各种结果类型)?我想要一个单独的评估者,这样我就不会事先知道结果的类型。我想要一个语言评估员。我是否需要为Exp添加值类型才能执行此操作?这看起来怎么样?什么样的值类型以及如何编辑当前的eval函数以反映这种新的多态类型

{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}

data Exp = V Var
    | B Bool
    | MyInt Int
    | And Exp Exp
    | Or Exp Exp
    | Not Exp
    | Mult Exp Exp
    | UnaryNeg Exp
    | LEQ Exp Exp
    | LESST Exp Exp
    | Add Exp Exp 
    | POLYEQ Exp Exp
data Var = VZ |VS Var

eval:: Exp -> Int
eval (MyInt e1)     = e1
eval (UnaryNeg e1)     = - (eval e1)
eval (Mult e1 e2) = eval e1 * eval e2
eval (Add e1 e2) = eval e1 + eval e2

eval0:: Exp -> Bool
eval0 (B e1) = e1
eval0 (Not e1) = not (eval0 e1)
eval0 (And e1 e2) = (eval0 e1) && (eval0 e2)
eval0 (Or e1 e2) = (eval0 e1) || (eval0 e2)
eval0 (LEQ e1 e2) = eval e1 <= eval e2
eval0 (LESST e1 e2) = eval e1 < eval e2

eval1:: Exp -> Bool
eval1 (POLYEQ e1 e2) = eval0 e1 == eval0 e2
{-#语言类型同义词实例,FlexibleInstances}
数据Exp=V变量
|布尔
|MyInt
|和经验
|或经验
|非经验
|综合出口
|一元负经验
|LEQ Exp
|莱斯特进出口
|添加Exp Exp
|聚醚试验
数据变量=VZ | VS变量
eval::Exp->Int
评估(MyInt e1)=e1
评估(一元负e1)=-(评估e1)
评估(多个e1 e2)=评估e1*评估e2
评估(添加e1 e2)=评估e1+评估e2
eval0::Exp->Bool
eval0(B e1)=e1
eval0(非e1)=非(eval0 e1)
eval0(和e1e2)=(eval0e1)和&(eval0e2)
eval0(或e1 e2)=(eval0 e1)| |(eval0 e2)
eval0(LEQ e1 e2)=eval e1 Bool
eval1(聚醚e1 e2)=eval0 e1==eval0 e2

标准解决方案是将表达式类型注释为它所表示的结果类型。这将是一种广义代数数据类型:

然后您只需要一个求值函数,其结果将是表达式所表示的任何类型:

eval :: Exp a -> a
eval (MyInt e1) = e1
eval (B  e1) = e1
...

为什么将
eval1
eval0
分开?它不需要在这里,但我的原始问题仍然存在,因为eval和eval0返回不同的类型。您前面两个问题的答案已经解释了如何执行此操作,即和。你尝试过这些解决方案吗?您遇到的问题是什么?另一种解决方案可能是返回
或Int Bool
。如果OP是一个初学者,它可能更容易开始。但我同意GADT将是另一种最好的解决方案,使用
other
仅解决部分问题,即返回格式良好的表达式的值,如
eval(Add(MyInt 3)(MyInt 5))==Right 8::other Bool Int
。它对诸如
Add(MyInt 3)(B False)
之类的“格式错误”表达式没有任何作用。您需要像
eval::Exp->Maybe(Bool Int)
这样的东西,而且定义中有太多的样板文件,与之相比,GADT并没有那么复杂。
eval :: Exp a -> a
eval (MyInt e1) = e1
eval (B  e1) = e1
...