-- list.hs: conjuring functions over lists (of ints) -- -- Copyright (C) 2021 Rudy Matela -- Distributed under the 3-Clause BSD licence (see the file LICENSE). import Conjure import Data.List (insert) length' :: [Int] -> Int length' [] = 0 length' [x] = 1 length' [x,y] = 2 length' [x,y,z] = 3 reverse' :: [Int] -> [Int] reverse' [] = [] reverse' [x] = [x] reverse' [x,y] = [y,x] reverse' [x,y,z] = [z,y,x] sort' :: [Int] -> [Int] sort' [] = [] sort' [x] = [x] sort' [x,y] | x <= y = [x,y] | otherwise = [y,x] sort' [x,y,z] | x <= y && y <= z = [x,y,z] | z <= y && y <= x = [z,y,x] (+++) :: [Int] -> [Int] -> [Int] [x] +++ [y] = [x,y] [x,y] +++ [z,w] = [x,y,z,w] [x,y,z] +++ [w,v,u] = [x,y,z,w,v,u] (\/) :: [Int] -> [Int] -> [Int] [x] \/ [y] = [x,y] [x,y] \/ [z,w] = [x,z,y,w] [x,y,z] \/ [w,v,u] = [x,w,y,v,z,u] main :: IO () main = do -- length xs = if null xs then 0 else 1 + length (tail xs) -- 1 2 3 4 5 6 7 8 9 conjure "length" length' [ val (0 :: Int) , val (1 :: Int) , value "+" ((+) :: Int -> Int -> Int) , value "tail" (tail :: [Int] -> [Int]) , value "null" (null :: [Int] -> Bool) ] -- reverse xs = if null xs then [] else reverse (tail xs) ++ [head xs] -- 1 2 3 4 5 6 7 8 9 10 11 12 -- needs size 11 with unit conjure "reverse" reverse' [ val ([] :: [Int]) , value "unit" ((:[]) :: Int -> [Int]) , value "++" ((++) :: [Int] -> [Int] -> [Int]) , value "head" (head :: [Int] -> Int) , value "tail" (tail :: [Int] -> [Int]) , value "null" (null :: [Int] -> Bool) ] -- sort xs = if null xs then [] else insert (head xs) (sort (tail xs)) -- 1 2 3 4 5 6 7 8 9 10 conjure "sort" sort' [ val ([] :: [Int]) , value "insert" (insert :: Int -> [Int] -> [Int]) , value "head" (head :: [Int] -> Int) , value "tail" (tail :: [Int] -> [Int]) , value "null" (null :: [Int] -> Bool) ] -- xs ++ ys = if null xs then ys else head xs:(tail xs ++ ys) -- 1 2 3 4 5 6 7 8 9 10 11 conjure "++" (+++) [ val ([] :: [Int]) , value ":" ((:) :: Int -> [Int] -> [Int]) , value "head" (head :: [Int] -> Int) , value "tail" (tail :: [Int] -> [Int]) , value "null" (null :: [Int] -> Bool) ] -- now through fold -- length xs = foldr (const (1 +)) 0 xs conjure "length" length' [ val (0 :: Int) , val (1 :: Int) , value "+" ((+) :: Int -> Int -> Int) , value "foldr" (foldr :: (Int -> Int -> Int) -> Int -> [Int] -> Int) , value "const" (const :: (Int -> Int) -> Int -> (Int -> Int)) -- cheating? ] -- now through fold and some cheating -- reverse xs = foldr (\x xs -> xs ++ [x]) [] xs -- reverse xs = foldr (flip (++) . unit) [] xs conjure "reverse" reverse' [ val ([] :: [Int]) , value "unit" ((:[]) :: Int -> [Int]) , value "++" ((++) :: [Int] -> [Int] -> [Int]) , value "foldr" (foldr :: (Int->[Int]->[Int]) -> [Int] -> [Int] -> [Int]) -- these last two are cheats: , value "flip" (flip :: ([Int]->[Int]->[Int]) -> [Int] -> [Int] -> [Int]) , value "." ((.) :: ([Int]->[Int]->[Int]) -> (Int->[Int]) -> Int -> [Int] -> [Int]) ] -- now through fold -- sort xs = foldr insert [] xs conjure "sort" sort' [ val ([] :: [Int]) , value "insert" (insert :: Int -> [Int] -> [Int]) , value "foldr" (foldr :: (Int -> [Int] -> [Int]) -> [Int] -> [Int] -> [Int]) ] -- now through fold -- xs ++ ys = foldr (:) ys xs conjure "++" (+++) [ val ([] :: [Int]) , value ":" ((:) :: Int -> [Int] -> [Int]) , value "foldr" (foldr :: (Int -> [Int] -> [Int]) -> [Int] -> [Int] -> [Int]) ] -- intercalate -- xs \/ ys = if null xs then ys else head xs : (ys \/ tail xs) conjure "\\/" (\/) [ val ([] :: [Int]) , value ":" ((:) :: Int -> [Int] -> [Int]) , value "head" (head :: [Int] -> Int) , value "tail" (tail :: [Int] -> [Int]) , value "null" (null :: [Int] -> Bool) ]