Haskell开关/案例使用

NuN*_*uNu 4 recursion haskell switch-statement

作为我在Haskell中编写的迷你解释器的一部分,我正在编写一个执行以下操作的函数:如果是eval (App e1 e2),我想递归计算e1(eval e1),将结果设置为v1.然后使用Switch/Case,我想检查模式,v1如果它不是Error,则递归计算e2(eval e2)并将该值设置为v2.使用这两个值v1v2,然后我申请的另一个功能(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)

这是一个很好的清洁方式来处理幕后的错误,同时专注于功能.