This commit is contained in:
2025-11-17 19:58:03 +01:00
parent e219436446
commit d91a947186
2 changed files with 48 additions and 45 deletions

View File

@ -2,14 +2,10 @@
module Assignment where
import Chi
import Control.Monad
import Control.Monad.Identity
import Debug.Trace (trace)
import Data.HashMap.Strict (HashMap)
import qualified Data.HashMap.Strict as HM
import Data.Functor ( (<&>) )
import Control.Monad.Identity (Identity(runIdentity))
-- Task 3
subst :: Variable -> Exp -> Exp -> Exp
subst var e = \case
Apply e1 e2 -> Apply (subst var e e1) (subst var e e2)
@ -22,27 +18,32 @@ subst var e = \case
substBr :: Br -> Br
substBr (Branch c vs e') = Branch c vs $ if var `notElem` vs then subst var e e' else e'
lookupBranch :: Constructor -> [Br] -> Identity ([Variable], Exp)
lookupBranch c [] = error "No matching branch"
lookupBranch c ((Branch c' bs e):brs) = if c == c' then pure (bs,e) else lookupBranch c brs
eval' :: Exp -> Identity Exp
eval' = \case
e@(Apply e1 e2) -> eval' e1 >>= \case
Lambda x e' -> eval' e2 >>= eval' . flip (subst x) e'
_ -> error $ "Function was not function in evaluation: " <> show e
Const c es -> mapM eval' es <&> Const c
Rec x e -> eval' $ subst x (Rec x e) e
Case e bs -> eval' e >>= \case
Const c vs -> lookupBranch c bs >>= \case
(xs,e') ->
if length vs /= length xs then error "Not the same amount of arguments in case" else
eval' $ foldr (uncurry subst) e' (zip xs vs)
e -> error $ "Non const in case: " <> show e
x -> pure x
-- Task 5
eval :: Exp -> Exp
eval = runIdentity . eval'
where
eval' :: Exp -> Identity Exp
eval' = \case
e@(Apply e1 e2) -> eval' e1 >>= \case
Lambda x e' -> eval' e2 >>= eval' . flip (subst x) e'
_ -> error $ "Function was not function in evaluation: " <> show e
Const c es -> mapM eval' es <&> Const c
Rec x e -> eval' $ subst x (Rec x e) e
Case e bs -> eval' e >>= \case
Const c vs -> lookupBranch c bs >>= \case
(xs,e') ->
if length vs /= length xs then error "Not the same amount of arguments in case" else
eval' $ foldr (uncurry subst) e' (zip xs vs)
e -> error $ "Non const in case: " <> show e
x -> pure x
lookupBranch :: Constructor -> [Br] -> Identity ([Variable], Exp)
lookupBranch c [] = error "No matching branch"
lookupBranch c ((Branch c' bs e):brs) =
if c == c'
then pure (bs,e)
else lookupBranch c brs
main :: IO ()
main = getLine >>= print . eval . parse