import Observe
-- Compute the last element in a list using append:
append :: [a] -> [a] -> [a]
append [] ys = ys
append (x:xs) ys = x : append xs ys
last :: Data a => [a] -> a
last xs | append ys [x] =:= xs
= x where x,ys free
-- We observe the usage of the function `last` on integer lists.
-- Note that we still observe the evaluation of free variables
-- occurring in the arguments.
last' :: [Int] -> Int
last' = observeG (oList oInt ~> oInt) "last" last
main1 :: Int
main1 = last' [1,2,3,4]
-- Observe a list of free variables.
main2 :: Int -> Int
main2 n = last' (take n (repeat x)) where x free
-- Important: compute only first solution by `:set +first`
main3 :: Bool
main3 = last' xs =:= 42 & length xs =:= 5 where xs free