1 {-# LANGUAGE BlockArguments #-}
2 {-# LANGUAGE TemplateHaskellQuotes #-}
3 {-# LANGUAGE NoMonomorphismRestriction #-}
5 module Symantic.Semantics.LetInserterSpec where
7 import Data.Function (($), (.))
8 import Data.Functor.Identity (Identity (..))
10 import Data.Maybe (Maybe (..))
11 import Data.Semigroup (Semigroup (..))
12 import Debug.Trace (trace)
13 import Language.Haskell.TH.Syntax qualified as TH
14 import Symantic.Semantics.LetInserter
15 import Symantic.Semantics.Viewer
16 import Symantic.Syntaxes.Classes (Abstractable (..), Constantable, Equalable (..), IfThenElseable (..), Instantiable (..), LetRecable (..), Letable (..), int, unit, (==))
18 import Test.Syd.Validity
19 import Text.Show (show)
20 import Prelude qualified as P
22 import Symantic.Syntaxes.Extras
24 -- import Debug.Trace (traceShow)
29 Constantable Int sem =>
39 Constantable Int sem =>
40 --GHC.Num.Num (sem Int) =>
43 t1 = (\x -> x * (x + int 1))
46 t2 x = let_ x (\y -> y * (y + int 1))
48 ft1 t x = lam (\u -> t x + t (x + u))
51 p12l loc = genLetAt loc (int 1 + int 2)
52 c1l = withLocus \loc -> p12l loc
54 ft11 loc = \t -> \x -> lam (\u -> t x + t (genLetAt loc (x + u)))
55 c3l1 = withLocus \loc -> ft11 loc t1 (p12l loc)
57 ft12 = \t -> \x -> lam (\u -> withLocus \loc -> t x + t (genLetAt loc (x + u)))
58 c3l2 = withLocus \loc -> ft12 t1 (p12l loc)
61 r12 = runIdentity (runLetInserter p12)
62 runLII = runIdentity . runLetInserter
65 -- letrec (fun self m -> lam @@ fun n ->
66 -- if_ (m =. int 0) (n + (int 1)) @@
67 -- if_ (n =. int 0) (self / (m - int 1) / int 1) @@
68 -- self / (m - int 1) / (self / m / (n - int 1))
69 -- ) @@ fun ack -> ack / int 2
74 ifThenElse (n == int 0) (log "n==0" (int 1)) $
75 ifThenElse (n == int 1) (log "n==1" (int 2)) $
85 ifThenElse (m == int 0) (n + int 1) $
86 ifThenElse (n == int 0) (self .@ (m - int 1) .@ int 1) $
87 self .@ (m - int 1) .@ (self .@ m .@ (n - int 1))
89 (\res -> res .@ int 2)
92 let rec loop n (x,y) =·
93 if n = 0 then x else if n = 1 then y else·
94 .< .~(loop (n-1) (x,y)) + .~(loop (n-2) (x,y)) >.
95 in .< fun x y -> .~(loop n (.< x >. , .< y >.)) >.
100 quote :: LetInserter (AnnotatedCode code) a -> LetInserter (AnnotatedCode code) a
101 -- quote :: sem a -> a
105 unquote :: a -> sem a
106 unquote = P.undefined
117 sem Int -> sem2 Int -> sem3 Int
120 , Abstractable (LetInserter (AnnotatedCode code))
122 ) => Int -> LetInserter (AnnotatedCode code) (Int -> Int -> Int)
125 if n P.== 0 then x else
126 if n P.== 1 then y else
127 quote (loop (n P.-1) (x, y) + loop (n P.-2) (x, y))
128 in quote (lam $ \x -> lam $ \y -> loop m (x, y))
132 (* Specialized to m. Without memoization, it diverges *)
134 with_locus_rec @@ fun l ->
135 let g = mkgenlet l (=) in
137 if m = 0 then .<fun n -> n + 1>. else
138 .<fun n -> if n = 0 then .~(g loop (m-1)) 1
139 else .~(g loop (m-1)) (.~(g loop m) (n-1))>.
143 -- https://en.wikipedia.org/wiki/Ackermann_function
144 -- Specialized to m. Without memoization, it diverges
148 Constantable Int code =>
150 IfThenElseable code =>
152 LetRecable Int code =>
154 Substractable code =>
156 LetInserter code (Int -> Int)
160 memoLoop k = genLetMemoRec l (P.fromIntegral k) (loop k)
162 traceShow (["sack", "loop"], ("m", 0 :: Int)) $
166 traceShow (["sack", "loop"], ("m", m)) $
170 (memoLoop (m P.- 1) .@ int 1)
171 (memoLoop (m P.- 1) .@ (memoLoop m .@ (n - int 1)))
175 -- https://simple.wikipedia.org/wiki/Fibonacci_number
181 LetRecable Int code =>
183 LetInserter code (Int -> Int -> Int)
185 withLocusRec $ \loc ->
187 memoLoop k = genLetMemoRec loc (P.fromIntegral k) (loop k)
190 then lam $ \x -> lam $ \_y -> x
193 then lam $ \_x -> lam $ \y -> y
194 else lam $ \x -> lam $ \y ->
196 .@ (memoLoop (n P.- 1) .@ x .@ y)
197 .@ (memoLoop (n P.- 2) .@ x .@ y)
201 -- (int -> int -> int) code =
202 -- .< fun x_1 -> fun y_2 -> (((y_2 + x_1) + y_2) + (y_2 + x_1)) + ((y_2 + x_1) + y_2)>.
203 tfib :: TH.Quote m => Int -> TH.Code m (Int -> Int -> Int)
211 else [||$$(loop (n P.- 1) (x, y)) P.+ $$(loop (n P.- 2) (x, y))||]
212 in [||\x y -> $$(loop m ([||x||], [||y||]))||]
215 acs :: Int -> LetInserter (AnnotatedCode Viewer) (Int -> Int)
219 (\self -> --lam $ \mm ->
221 --if (runIdentity m P.== 0) then (n + int 1) else
222 ifThenElse (n == int 0) n $
224 (self .@ int m) .@ (n - int 1)
225 --ifThenElse (m == int 0) (n + int 1) $
226 --ifThenElse (n == int 0) (self .@ (m - int 1) .@ int 1) $
227 --genLetMemo l m $ self .@ (m - int 1) .@ (self .@ m .@ (n - int 1))
229 (\self -> genLetMemoRec l (2) (self .@ int 2))
231 ack :: Int -> Int -> Int
232 ack 0 n = trace ("ack 0 " <> show n) $ n P.+ 1
233 ack m 0 = trace ("ack " <> show m <> " 0") $ ack (m P.- 1) 1
234 ack m n = trace ("ack " <> show n <> " " <> show m) $ ack (m P.- 1) (ack m (n P.- 1))
239 it "can bind a literal" do
240 view (runLetInserter (let_ (int 3) (\v -> int 4 + v)))
241 `shouldBe` "let x1 = 3 in 4 + x1"
242 it "can bind an expression of literals" do
243 view (runLetInserter (let_ (int 1 + int 2) (\v -> int 4 + v)))
244 `shouldBe` "let x1 = 1 + 2 in 4 + x1"
245 it "can bind a variable" do
246 view (runLetInserter (lam (\x -> let_ x (\v -> int 4 + v))))
247 `shouldBe` "\\x1 -> let x2 = x1 in 4 + x2"
248 it "can bind an expression with a variable" do
249 view (runLetInserter (lam (\x -> let_ (x + int 1) (\v -> int 4 + v))))
250 `shouldBe` "\\x1 -> let x2 = x1 + 1 in 4 + x2"
253 let exp = int 1 + genLet (int 2)
254 view (runLetInserter exp) `shouldBe` "let x1 = 2 in 1 + x1"
255 runIdentity (runLetInserter exp) `shouldBe` 3
256 it "can bind a literal across a lambda" do
257 let exp = lam (\x -> x + genLet (int 2))
258 view (runLetInserter exp) `shouldBe` "let x1 = 2 in \\x2 -> x2 + x1"
259 runIdentity (runLetInserter exp) 1 `shouldBe` 3
260 it "can bind an operation across a lambda" do
261 let exp = lam (\x -> x + genLet (int 1 + int 2))
262 view (runLetInserter exp) `shouldBe` "let x1 = 1 + 2 in \\x2 -> x2 + x1"
263 runIdentity (runLetInserter exp) 1 `shouldBe` 4
264 it "can wrap a variable" do
265 let exp = lam (\x -> withLocus (\l -> x + genLetAt l x))
266 view (runLetInserter exp) `shouldBe` "\\x1 -> let x2 = x1 in x1 + x2"
267 runIdentity (runLetInserter exp) 1 `shouldBe` 2
268 -- This must not raise a lookupVar failure for var=([1]) env=[]
269 it "cannot cause a scope extrusion using withLocus" do
270 view (runLetInserter (withLocus (\l -> lam (\x -> x + genLetAt l x))))
271 `shouldBe` "\\x1 -> let x2 = x1 in x1 + x2"
272 -- Check that 'lam' limits the scope extrusion:
273 -- as soon as that passing a virtual binding would
274 -- make a variable extrude its scope, this virtual binding is bound.
275 it "has its locus limited by lam when wrapping its variable" do
276 let exp = lam (\x -> x + genLet x)
277 view (runLetInserter exp) `shouldBe` "\\x1 -> let x2 = x1 in x1 + x2"
278 runIdentity (runLetInserter exp) 1 `shouldBe` 2
279 it "does not have its locus limited by lam when not wrapping its variable" do
280 let exp = lam (\x -> x + genLet (int 1))
281 view (runLetInserter exp) `shouldBe` "let x1 = 1 in \\x2 -> x2 + x1"
282 runIdentity (runLetInserter exp) 1 `shouldBe` 2
283 it "can wrap let_" do
284 let exp = lam (\x -> x + genLet (let_ (int 1) (\y -> y)))
285 view (runLetInserter exp) `shouldBe` "let x1 = let x2 = 1 in x2 in \\x2 -> x2 + x1"
286 runIdentity (runLetInserter exp) 1 `shouldBe` 2
287 it "can have its locus limited by withLocus" do
288 let exp = lam (\x -> withLocus (\l -> x + genLetAt l (let_ (int 1) (\y -> y))))
289 view (runLetInserter exp) `shouldBe` "\\x1 -> let x2 = let x3 = 1 in x3 in x1 + x2"
290 runIdentity (runLetInserter exp) 1 `shouldBe` 2
291 it "can wrap lam and a variable" do
292 let exp = lam (\x -> x + genLet (lam (\_y -> x)) .@ unit)
293 view (runLetInserter exp) `shouldBe` "\\x1 -> let x2 = \\x3 -> x1 in x1 + x2 ()"
294 runIdentity (runLetInserter exp) 1 `shouldBe` 2
295 it "can wrap lam and be called" do
296 let exp = lam (\x -> x + genLet (lam (\y -> y + int 2)) .@ x)
297 view (runLetInserter exp) `shouldBe` "let x1 = \\x2 -> x2 + 2 in \\x2 -> x2 + x1 x2"
298 runIdentity (runLetInserter exp) 1 `shouldBe` 4
299 it "can wrap a variable in an operation" do
300 let exp = lam (\x -> x + genLet (x + int 1))
301 view (runLetInserter exp) `shouldBe` "\\x1 -> let x2 = x1 + 1 in x1 + x2"
302 runIdentity (runLetInserter exp) 1 `shouldBe` 3
303 it "can wrap literals inside an expression with two variables" do
304 let exp = lam (\x -> lam (\y -> x + y + genLet (int 2 + int 3)))
305 view (runLetInserter exp) `shouldBe` "let x1 = 2 + 3 in \\x2 -> \\x3 -> x2 + x3 + x1"
306 runIdentity (runLetInserter exp) 1 4 `shouldBe` 10
307 it "can wrap the farthest variable inside two lam" do
308 let exp = lam (\x -> lam (\y -> x + y + genLet x))
309 view (runLetInserter exp) `shouldBe` "\\x1 -> let x2 = x1 in \\x3 -> x1 + x3 + x2"
310 runIdentity (runLetInserter exp) 1 4 `shouldBe` 6
311 it "can wrap another variable inside two lam" do
312 let exp = lam (\x -> lam (\y -> x + y + genLet y))
313 view (runLetInserter exp) `shouldBe` "\\x1 -> \\x2 -> let x3 = x2 in x1 + x2 + x3"
314 runIdentity (runLetInserter exp) 1 4 `shouldBe` 9
315 it "can wrap another variable inside two lam" do
316 let exp = lam (\x -> lam (\y -> x + y + genLet y))
317 view (runLetInserter exp) `shouldBe` "\\x1 -> \\x2 -> let x3 = x2 in x1 + x2 + x3"
318 runIdentity (runLetInserter exp) 1 4 `shouldBe` 9
319 it "can wrap the farthest variable in an expression inside two lam" do
320 let exp = lam (\x -> lam (\y -> x + y + genLet (x + int 1)))
321 view (runLetInserter exp) `shouldBe` "\\x1 -> let x2 = x1 + 1 in \\x3 -> x1 + x3 + x2"
322 runIdentity (runLetInserter exp) 1 4 `shouldBe` 7
323 it "can wrap the closest variable in an expression inside two lam" do
324 let exp = lam (\x -> lam (\y -> x + y + genLet (y + int 1)))
325 view (runLetInserter exp) `shouldBe` "\\x1 -> \\x2 -> let x3 = x2 + 1 in x1 + x2 + x3"
326 runIdentity (runLetInserter exp) 1 4 `shouldBe` 10
327 it "can wrap both variables in an expression inside two lam" do
328 let exp = lam (\x -> lam (\y -> x + y + genLet (y + int 1 + x)))
329 view (runLetInserter exp) `shouldBe` "\\x1 -> \\x2 -> let x3 = x2 + 1 + x1 in x1 + x2 + x3"
330 runIdentity (runLetInserter exp) 1 4 `shouldBe` 11
331 it "can be nested" do
332 let exp = lam (\x -> lam (\y -> x + y + genLet (genLet (y + int 1 + x))))
333 view (runLetInserter exp) `shouldBe` "\\x1 -> \\x2 -> let x3 = x2 + 1 + x1 in let x4 = x3 in x1 + x2 + x4"
334 runIdentity (runLetInserter exp) 1 4 `shouldBe` 11
335 it "can be nested within an expression of literals" do
336 let exp = lam (\x -> lam (\y -> x + y + genLet (y + genLet (int 1 + int 2))))
337 view (runLetInserter exp) `shouldBe` "let x1 = 1 + 2 in \\x2 -> \\x3 -> let x4 = x3 + x1 in x2 + x3 + x4"
338 runIdentity (runLetInserter exp) 1 4 `shouldBe` 12
339 it "can be nested within an expression with a variable" do
340 let exp = lam (\x -> lam (\y -> x + y + genLet (y + genLet (int 1 + x))))
341 view (runLetInserter exp) `shouldBe` "\\x1 -> let x2 = 1 + x1 in \\x3 -> let x4 = x3 + x2 in x1 + x3 + x4"
342 runIdentity (runLetInserter exp) 1 4 `shouldBe` 11
343 it "can be nested within an expression with two variables" do
344 let exp = lam (\x -> lam (\y -> x + y + genLet (y + genLet (int 1 + x + y))))
345 view (runLetInserter exp) `shouldBe` "\\x1 -> \\x2 -> let x3 = 1 + x1 + x2 in let x4 = x2 + x3 in x1 + x2 + x4"
346 runIdentity (runLetInserter exp) 1 4 `shouldBe` 15
347 it "can be nested within another expression with two variables" do
348 let exp = lam (\x -> lam (\y -> x + y + genLet (x + genLet (int 1 + x + y))))
349 view (runLetInserter exp) `shouldBe` "\\x1 -> \\x2 -> let x3 = 1 + x1 + x2 in let x4 = x1 + x3 in x1 + x2 + x4"
350 runIdentity (runLetInserter exp) 1 4 `shouldBe` 12
351 it "can be nested within an expression of literals and one variable" do
352 let exp = lam (\x -> lam (\y -> x + y + genLet (int 1 + genLet (int 1 + x + int 2))))
353 view (runLetInserter exp) `shouldBe` "\\x1 -> let x2 = 1 + x1 + 2 in let x3 = 1 + x2 in \\x4 -> x1 + x4 + x3"
354 runIdentity (runLetInserter exp) 1 4 `shouldBe` 10
355 it "can be nested within an expression of literals" do
356 let exp = lam (\x -> lam (\y -> x + y + genLet (int 1 + genLet (int 1 + int 2 + int 3))))
357 view (runLetInserter exp) `shouldBe` "let x1 = 1 + 2 + 3 in let x2 = 1 + x1 in \\x3 -> \\x4 -> x3 + x4 + x2"
358 runIdentity (runLetInserter exp) 1 4 `shouldBe` 12
359 it "duplicates literals when used with host-let" do
360 let exp = let x = genLet (int 1 + int 2) in x + x
361 view (runLetInserter exp) `shouldBe` "let x1 = 1 + 2 in let x2 = 1 + 2 in x1 + x2"
362 runIdentity (runLetInserter exp) `shouldBe` 6
363 it "duplicates literals when using host-let and no specific memo key" do
365 let x = genLet (int 1 + int 2)
366 in let y = genLet (int 1 + x)
368 view (runLetInserter exp) `shouldBe` "let x1 = 1 + 2 in let x2 = 1 + 2 in let x3 = 1 + x2 in x1 + x3"
369 runIdentity (runLetInserter exp) `shouldBe` 7
370 it "does not duplicate host-let when using a specific memo key" do
372 let x = genLetMemoAtMaybe (Just 0) Nothing (int 1 + int 2)
373 in let y = genLet (int 1 + x)
375 view (runLetInserter exp) `shouldBe` "let x1 = 1 + 2 in let x2 = 1 + x1 in x1 + x2"
376 runIdentity (runLetInserter exp) `shouldBe` 7
377 it "does not duplicate host-lets when using specific memo keys" do
379 let x = genLetMemoAtMaybe (Just 0) Nothing (int 1 + int 2)
380 in let y = genLetMemoAtMaybe (Just 1) Nothing (int 1 + x)
381 in let z = genLet (int 1 + y)
383 view (runLetInserter exp) `shouldBe` "let x1 = 1 + 2 in let x2 = 1 + x1 in let x3 = 1 + x2 in x1 + x3 + x2"
384 runIdentity (runLetInserter exp) `shouldBe` 12
385 it "does not duplicate host-let when using a specific memo key, inside a lam" do
388 let x = genLetMemoAtMaybe (Just 0) Nothing (int 1 + int 2)
389 in let y = genLet (u + x)
391 view (runLetInserter exp) `shouldBe` "let x1 = 1 + 2 in \\x2 -> let x3 = x2 + x1 in x1 + x3"
392 runIdentity (runLetInserter exp) 2 `shouldBe` 8
393 it "does not duplicate host-let when using a specific memo key, inside a lam and using its variable" do
396 let x = genLetMemoAtMaybe (Just 0) Nothing (u + int 2)
397 in let y = genLet (int 1 + x)
399 view (runLetInserter exp) `shouldBe` "\\x1 -> let x2 = x1 + 2 in let x3 = 1 + x2 in x2 + x3"
400 runIdentity (runLetInserter exp) 2 `shouldBe` 9
401 it "does not duplicate host-lets when using specific memo keys, inside a lam and using its variable" do
404 let x = genLetMemoAtMaybe (Just 0) Nothing (u + int 2)
405 in let y = genLetMemoAtMaybe (Just 1) Nothing (int 1 + x)
406 in let z = genLetMemoAtMaybe (Just 2) Nothing (int 1 + y)
408 view (runLetInserter exp) `shouldBe` "\\x1 -> let x2 = x1 + 2 in let x3 = 1 + x2 in let x4 = 1 + x3 in x2 + x4 + x3 + x4"
409 runIdentity (runLetInserter exp) 2 `shouldBe` 21
412 runLII p12 `shouldBe` 3
414 view (runLetInserter p12)
417 view (runLetInserter c1)
418 `shouldBe` "(1 + 2) * (1 + 2 + 1)"
420 view (runLetInserter c2)
421 `shouldBe` "let x1 = 1 + 2 in x1 * (x1 + 1)"
423 view (runLetInserter c3)
424 `shouldBe` "\\x1 -> (let x2 = 1 + 2 in x2 * (x2 + 1)) + (let x2 = 1 + 2 + x1 in x2 * (x2 + 1))"
427 view (runLetInserter c1l)
428 `shouldBe` "let x1 = 1 + 2 in x1"
429 -- , it "c3l1" do -- expected scope extrusion
430 -- view (runLetInserter c3l1) `shouldBe` ""
432 -- serious duplication
433 view (runLetInserter c3l2)
434 `shouldBe` "let x1 = 1 + 2 in let x2 = 1 + 2 in let x3 = 1 + 2 in let x4 = 1 + 2 in \\x5 -> let x6 = x3 + x5 in let x7 = x4 + x5 in x1 * (x2 + 1) + x6 * (x7 + 1)"
435 it "let x1 = 1 in let x2 = 2 in x1 + x2" do
436 let exp = withLocus $ \loc -> genLetAt loc (int 1) + genLetAt loc (int 2)
437 view (runLetInserter exp)
438 `shouldBe` "let x1 = 1 in let x2 = 2 in x1 + x2"
439 it "let_ (genLetAt loc (int 1 + int 2)) (\\x -> x + x)" do
440 let exp = withLocus $ \loc ->
441 let_ (genLetAt loc (int 1 + int 2)) $ \x ->
443 view (runLetInserter exp)
444 `shouldBe` "let x1 = 1 + 2 in let x2 = x1 in x2 + x2"
445 it "withLocus does not cause a scope extrusion" do
446 let exp = withLocus $ \loc1 ->
449 loc1 -- expected scope extrusion if it's not bound at loc2 instead of loc1
450 (int 1 + genLetAt loc2 (int 2))
452 view (runLetInserter exp)
453 `shouldBe` "let x1 = 2 in let x2 = 1 + x1 in x2 * 3"
454 it "let x1 = 1 + 2 in let x2 = 1 + 2 in let x3 = 1 + x2 in x1 + x3" do
455 let exp = withLocus $ \loc ->
456 let x = (genLetAt loc (int 1 + int 2))
457 in let y = (genLetAt loc (int 1 + x))
459 view (runLetInserter exp)
460 `shouldBe` "let x1 = 1 + 2 in let x2 = 1 + 2 in let x3 = 1 + x2 in x1 + x3"
461 -- , it "let x1 = 1 + 2 in let x2 = 1 + x1 in x1 + x2" do
462 -- let exp = withLocus $ \loc ->
463 -- let__ (genLetAt loc (int 1 + int 2)) $ \x ->
464 -- let__ (genLetAt loc (int 1 + x)) $ \y ->
466 -- view (runLetInserter exp) `shouldBe`
467 -- "let x1 = 1 + 2 in let x2 = 1 + x1 in x1 + x2"
468 it "let x1 = 1 + 2 in let x2 = x1 in let x3 = 1 + x2 in let x4 = x3 in x2 + x4" do
469 let exp = withLocus $ \loc ->
470 let_ (genLetAt loc (int 1 + int 2)) $ \x ->
472 let_ (genLetAt locX (int 1 + x)) $ \y ->
474 view (runLetInserter exp)
475 `shouldBe` "let x1 = 1 + 2 in let x2 = x1 in let x3 = 1 + x2 in let x4 = x3 in x2 + x4"
476 describe "Fibonacci" do
478 view (runLetInserter (fibonacci 2))
479 `shouldBe` "letRec [u1 = \\x2 -> \\x3 -> x3,u2 = \\x2 -> \\x3 -> x2] in \\x3 -> \\x4 -> u1 x3 x4 + u2 x3 x4"
481 view (runLetInserter (fibonacci 5))
482 `shouldBe` "letRec [u1 = \\x2 -> \\x3 -> u2 x2 x3 + u3 x2 x3,u2 = \\x2 -> \\x3 -> u3 x2 x3 + u4 x2 x3,u3 = \\x2 -> \\x3 -> u4 x2 x3 + u5 x2 x3,u4 = \\x2 -> \\x3 -> x3,u5 = \\x2 -> \\x3 -> x2] in \\x6 -> \\x7 -> u1 x6 x7 + u2 x6 x7"
484 runIdentity (runLetInserter (fibonacci 2)) 0 1 `shouldBe` 1
486 runIdentity (runLetInserter (fibonacci 5)) 0 1 `shouldBe` 5
488 runIdentity (runLetInserter (fibonacci 10)) 0 1 `shouldBe` 55
489 describe "Ackermann" do
491 view (runLetInserter (sack 2))
492 `shouldBe` "letRec [u1 = \\x2 -> if x2 == 0 then u2 1 else u2 (u1 (x2 - 1)),u2 = \\x2 -> if x2 == 0 then u3 1 else u3 (u2 (x2 - 1)),u3 = \\x2 -> x2 + 1] in u1"
494 runLII (sack 2) 3 `shouldBe` 9
496 runLII (sack 3) 4 `shouldBe` 125
500 -- runLII (fib .@ int 0) `shouldBe` 1
502 -- runLII (fib .@ int 1) `shouldBe` 2
504 -- runLII (fib .@ int 2) `shouldBe` 42
506 -- runIdentity (fib .@ int 1) `shouldBe` 2
508 -- runIdentity (sack .@ int 3) `shouldBe` 9
510 -- view (runLetInserter acs) `shouldBe` ""