NuN*_*uNu 4 recursion haskell switch-statement
作为我在Haskell中编写的迷你解释器的一部分,我正在编写一个执行以下操作的函数:如果是eval (App e1 e2),我想递归计算e1(eval e1),将结果设置为v1.然后使用Switch/Case,我想检查模式,v1如果它不是Error,则递归计算e2(eval e2)并将该值设置为v2.使用这两个值v1和v2,然后我申请的另一个功能(appVals这些值).
eval :: Exp -> Error Val
eval (App e1 e2) = appVals v1 v2 where
v1 = case (eval e1) of
Error err -> Error "Not an application"
/= Error err -> eval e1 = v1
v2 = case (eval e2) of
Error err -> Error "Not an application"
/= Error err -> eval e2 = v2
Run Code Online (Sandbox Code Playgroud)
我想我可能已经弄明白但我并不完全确定我已正确完成开关/外壳部件.任何想法/建议?
And*_*ewC 12
你的案例陈述的第二部分不应该试图重新测试,因为你已经知道它不是Error- 那将与第一部分相匹配.(跳过/= Error err.)
eval e1 = v1尝试重做你在开始时做的eval.你不需要这样做.
这是我认为你打算做的事情:
eval :: Exp -> Error Val
eval (App e1 e2) = case eval e1 of
Error _ -> Error "Not an application"
S v1 -> case eval e2 of -- nested case statement
Error _ -> Error "Not an application"
S v2 -> appVals v1 v2 -- match the S away
Run Code Online (Sandbox Code Playgroud)
但这一切看起来都有点难看,所以让我们从加布里埃尔·冈萨雷斯那里得到优秀的建议,然后再做一个应用Error.
instance Functor Error where
fmap f (Error e) = Error e -- pass through errors
fmap f (S x) = S (f x) -- edit successes
Run Code Online (Sandbox Code Playgroud)
例如,fmap (+4) (Error "oops") = Error "oops"然而fmap (+4) (S 5) = S 9.
如果这fmap对您来说都是新手,为什么不阅读Functors教程?
接下来让我们创建一个Applicative实例.Applicative允许您使用复杂的功能,如简单的功能.您需要import Control.Applicative在文件的顶部才能使其正常工作.
instance Applicative Error where
pure x = S x -- how to put ordinary data in
S f <*> S x = S (f x)
Error e <*> _ = Error e
_ <*> Error e = Error e
Run Code Online (Sandbox Code Playgroud)
现在,如果没有任何错误,那么你就定义了
appVal' :: Val -> Val -> Val
eval' :: Exp -> Val
eval' (App e1 e2) = appVal' (eval' e1) (eval' e2)
Run Code Online (Sandbox Code Playgroud)
使用applicative,我们可以使用<$>哪个工作有点像,$除了它做你定义的任何管道fmap.同样,<*>有点像函数应用程序,除了额外的管道,所以我们可以定义
eval :: Exp -> Error Val
eval (App e1 e2) = appVals <$> eval e1 <*> eval e2
Run Code Online (Sandbox Code Playgroud)
这是一个很好的清洁方式来处理幕后的错误,同时专注于功能.
| 归档时间: |
|
| 查看次数: |
1645 次 |
| 最近记录: |