diff options
Diffstat (limited to 'ws2015')
-rw-r--r-- | ws2015/FFP/blaetter/04/FFP_U04_Lazy.hs | 116 |
1 files changed, 110 insertions, 6 deletions
diff --git a/ws2015/FFP/blaetter/04/FFP_U04_Lazy.hs b/ws2015/FFP/blaetter/04/FFP_U04_Lazy.hs index b84ad0b..36c0578 100644 --- a/ws2015/FFP/blaetter/04/FFP_U04_Lazy.hs +++ b/ws2015/FFP/blaetter/04/FFP_U04_Lazy.hs | |||
@@ -20,6 +20,9 @@ import Data.Set (Set) | |||
20 | import qualified Data.List as List ((\\)) | 20 | import qualified Data.List as List ((\\)) |
21 | 21 | ||
22 | import Data.Maybe (fromMaybe) | 22 | import Data.Maybe (fromMaybe) |
23 | import Data.Tuple (swap) | ||
24 | |||
25 | import Control.Applicative (Applicative(..), (<$>)) | ||
23 | 26 | ||
24 | ---- A4-1 Verzögerte Auswertung | 27 | ---- A4-1 Verzögerte Auswertung |
25 | -- Gegeben ist folgendes Programm: | 28 | -- Gegeben ist folgendes Programm: |
@@ -156,6 +159,8 @@ rel2S = Set.fromList . rel2 | |||
156 | -- Implementieren Sie die Aufgabe noch mal ganz schnell | 159 | -- Implementieren Sie die Aufgabe noch mal ganz schnell |
157 | -- ohne Rücksicht auf Zirkularität oder Effizienz, | 160 | -- ohne Rücksicht auf Zirkularität oder Effizienz, |
158 | -- sondern ganz bequem mit der Standardbibliothek für Data.Set | 161 | -- sondern ganz bequem mit der Standardbibliothek für Data.Set |
162 | |||
163 | -- The implementation below seems to me no nicer than a :( | ||
159 | 164 | ||
160 | transClS :: (Ord a) => (a -> Set a) -> Set a -> Set a | 165 | transClS :: (Ord a) => (a -> Set a) -> Set a -> Set a |
161 | transClS rel xs = build xs Set.empty | 166 | transClS rel xs = build xs Set.empty |
@@ -283,18 +288,23 @@ evalStrict :: Term -> Term | |||
283 | evalStrict t = showMem $ evalS0 t | 288 | evalStrict t = showMem $ evalS0 t |
284 | 289 | ||
285 | -- Die Funktion evalS0 ist nur eine Kurzform, um die Auswertung mit leerem Speicher zu starten: | 290 | -- Die Funktion evalS0 ist nur eine Kurzform, um die Auswertung mit leerem Speicher zu starten: |
286 | evalS0 ::Term -> (Memory, Term) | 291 | evalS0 :: Term -> (Memory, Term) |
287 | evalS0 = evalS Map.empty | 292 | evalS0 = evalS Map.empty |
288 | 293 | ||
289 | -- Ihre Aufgabe ist es also, evalS zu implementieren: | 294 | -- Ihre Aufgabe ist es also, evalS zu implementieren: |
290 | 295 | ||
291 | evalS :: Memory -> Term -> (Memory, Term) | 296 | evalS :: Memory -> Term -> (Memory, Term) |
292 | evalS m x@(Var v) = (,) m $ fromMaybe x $ Map.lookup v m | 297 | evalS m x@(Var v) = (,) m $ fromMaybe x $ Map.lookup v m |
293 | evalS m (App f x) = case f' of | 298 | evalS m t@(App f x) = case f' of |
294 | (Abs v t) -> undefined | 299 | (Abs v t) -> let |
295 | t -> evalS m' t | 300 | usedVars = Set.unions $ (Map.keysSet m'' :) $ map freeVars $ Map.elems m'' |
301 | v' = generateFreshVar usedVars | ||
302 | (m'', x') = evalS m' x | ||
303 | m''' = Map.insert v' x' m'' | ||
304 | in evalS m''' $ subst (v,Var v') t | ||
305 | _ -> (m, t) | ||
296 | where | 306 | where |
297 | (m', f') <- evalS m f | 307 | (m', f') = evalS m f |
298 | evalS m x = (m, x) | 308 | evalS m x = (m, x) |
299 | 309 | ||
300 | -- Dabei verfolgen wir folgende Auswertestrategie: | 310 | -- Dabei verfolgen wir folgende Auswertestrategie: |
@@ -339,9 +349,103 @@ evalL0 ::Term -> (Memory, Term) | |||
339 | evalL0 = evalL Map.empty | 349 | evalL0 = evalL Map.empty |
340 | 350 | ||
341 | evalL :: Memory -> Term -> (Memory, Term) | 351 | evalL :: Memory -> Term -> (Memory, Term) |
342 | evalL = undefined -- !!! TODO !!! | 352 | evalL m x@(Var v) = case Map.lookup v m of |
353 | Nothing -> (m, x) | ||
354 | Just t -> let | ||
355 | (m', t') = evalL m t | ||
356 | in (Map.insert v t' m', t') | ||
357 | evalL m t@(App f x) = case f' of | ||
358 | (Abs v t) -> let | ||
359 | usedVars = Set.unions $ (Map.keysSet m' :) $ map freeVars $ Map.elems m' | ||
360 | v' = generateFreshVar usedVars | ||
361 | m'' = Map.insert v' x m' | ||
362 | in evalL m'' $ subst (v,Var v') t | ||
363 | _ -> (m, t) | ||
364 | where | ||
365 | (m', f') = evalL m f | ||
366 | evalL m x = (m, x) | ||
367 | |||
368 | |||
369 | |||
370 | -- I am of the considered opinion that the above exercises call for State. Therefore: | ||
371 | |||
372 | data State s a = State { unState :: s -> (a, s) } | ||
373 | |||
374 | instance Functor (State s) where | ||
375 | fmap f (State g) = State ((\(a, s) -> (f a, s)) . g) | ||
376 | |||
377 | instance Applicative (State s) where | ||
378 | pure a = State (\s -> (a, s)) | ||
379 | (State f) <*> (State g) = State (\s -> (\(g', s) -> (\(f', s') -> (f' g', s')) $ f s) $ g s) | ||
380 | |||
381 | instance Monad (State s) where | ||
382 | return = pure | ||
383 | (State f) >>= g = State ((\(a, s) -> (unState $ g a) s) . f) | ||
343 | 384 | ||
385 | get :: State s s | ||
386 | get = State (\s -> (s, s)) | ||
344 | 387 | ||
388 | put :: s -> State s () | ||
389 | put s = State (\_ -> ((), s)) | ||
390 | |||
391 | modify :: (s -> s) -> State s () | ||
392 | modify f = (f <$> get) >>= put | ||
393 | |||
394 | evalStrict' :: Term -> Term | ||
395 | evalStrict' t = showMem $ evalS0' t | ||
396 | where | ||
397 | evalS0' = evalS' Map.empty | ||
398 | |||
399 | evalLazy' :: Term -> Term | ||
400 | evalLazy' t = showMem $ evalL0' t | ||
401 | where | ||
402 | evalL0' = evalL' Map.empty | ||
403 | |||
404 | evalS' :: Memory -> Term -> (Memory, Term) | ||
405 | evalS' m t = swap $ (unState $ eval t) m | ||
406 | where | ||
407 | eval :: Term -> State Memory Term | ||
408 | eval t@(Var v) = (fromMaybe t . Map.lookup v) <$> get | ||
409 | eval t@(App f x) = do | ||
410 | f' <- eval f | ||
411 | case f' of | ||
412 | (Abs v t) -> do | ||
413 | x' <- eval x | ||
414 | mem <- get | ||
415 | let | ||
416 | boundInTerms = Set.unions . map freeVars $ Map.elems mem | ||
417 | usedVars = boundInTerms `Set.union` Map.keysSet mem | ||
418 | v' = generateFreshVar usedVars | ||
419 | modify $ Map.insert v' x' | ||
420 | eval $ subst (v, Var v') t | ||
421 | _ -> pure t | ||
422 | eval t = pure t | ||
423 | |||
424 | evalL' :: Memory -> Term -> (Memory, Term) | ||
425 | evalL' m t = swap $ (unState $ eval t) m | ||
426 | where | ||
427 | eval :: Term -> State Memory Term | ||
428 | eval t@(Var v) = do | ||
429 | t' <- Map.lookup v <$> get | ||
430 | case t' of | ||
431 | Nothing -> return t | ||
432 | Just t -> do | ||
433 | t' <- eval t | ||
434 | modify $ Map.insert v t' | ||
435 | return t' | ||
436 | eval t@(App f x) = do | ||
437 | f' <- eval f | ||
438 | case f' of | ||
439 | (Abs v t) -> do | ||
440 | mem <- get | ||
441 | let | ||
442 | boundInTerms = Set.unions . map freeVars $ Map.elems mem | ||
443 | usedVars = boundInTerms `Set.union` Map.keysSet mem | ||
444 | v' = generateFreshVar usedVars | ||
445 | modify $ Map.insert v' x | ||
446 | eval $ subst (v, Var v') t | ||
447 | _ -> pure t | ||
448 | eval t = pure t | ||
345 | 449 | ||
346 | ----------------------------------------------------------------------- | 450 | ----------------------------------------------------------------------- |
347 | -- ANHANG | 451 | -- ANHANG |