{-@ LIQUID "--reflection" @-}
module Data.List where
import Prelude hiding ( map
, max
, zipWith
, all
, foldr
)
{-@ type SameLen L = {v:_|llen v = llen L} @-}
{-@ type ListN N = {v:_|llen v = N} @-}
data List a = Nil | Cons a (List a)
deriving (Eq, Show)
{-@ reflect consDouble @-}
{-@ consDouble :: Double -> xs:List Double -> {v:List Double | llen v == llen xs + 1 } @-}
consDouble :: Double -> List Double -> List Double
consDouble = Cons
{-@ measure llen @-}
{-@ llen :: List a -> Nat @-}
llen :: List a -> Int
llen Nil = 0
llen (Cons _ xs) = 1 + llen xs
{-@ type Idx V = {i:Int | 0 <= i && i < llen V} @-}
{-@ reflect at @-}
{-@ at :: xs:List a -> Idx xs -> a @-}
at :: List a -> Int -> a
at (Cons x _) i | i == 0 = x
at (Cons _ xs) i = at xs (i - 1)
{-@ reflect range @-}
{-@ range :: i:Nat -> len:Nat -> {v:List {j:Nat|j < i + len}|llen v = len} / [len] @-}
range :: Int -> Int -> List Int
range _ 0 = Nil
range i len = Cons i (range (i + 1) (len - 1))
{-@ reflect map @-}
{-@ map :: (a -> b) -> xs:List a -> {ys:List b|llen ys = llen xs} @-}
map :: (a -> b) -> List a -> List b
map f Nil = Nil
map f (Cons x xs) = Cons (f x) (map f xs)
zipWith :: (a -> b -> c) -> List a -> List b -> List c
zipWith _ Nil _ = Nil
zipWith _ _ Nil = Nil
zipWith f (Cons x xs) (Cons x' xs') = Cons (f x x') (zipWith f xs xs')
all :: List Bool -> Bool
all Nil = True
all (Cons x xs) = x && all xs
{-@ reflect max @-}
max :: Double -> Double -> Double
max a b = if a < b then b else a
{-@ reflect pow @-}
{-@ pow :: {v:Double|v >= 0} -> i:Nat -> {v:Double|v >= 0} / [i] @-}
pow :: Double -> Int -> Double
pow x 0 = 1
pow x i = x * pow x (i - 1)
{-@ reflect ap @-}
ap :: List (a -> b) -> List a -> List b
ap _ Nil = Nil
ap Nil _ = Nil
ap (Cons f fs) (Cons x xs) = Cons (f x) (ap fs xs)
{-@ reflect zip3With @-}
zip3With :: (a -> b -> c -> d) -> List a -> List b -> List c -> List d
zip3With _ Nil _ _ = Nil
zip3With _ _ Nil _ = Nil
zip3With _ _ _ Nil = Nil
zip3With f (Cons a as) (Cons b bs) (Cons c cs) = Cons (f a b c) (zip3With f as bs cs)
{-@ zip4 :: as:List a -> {bs:List b|llen bs = llen as} -> {cs:List c|llen cs = llen as} -> {ds:List d|llen ds = llen as} -> List (a, b, c, d) @-}
zip4 :: List a -> List b -> List c -> List d -> List (a, b, c, d)
zip4 Nil Nil Nil Nil = Nil
zip4 (Cons a as) (Cons b bs) (Cons c cs) (Cons d ds) = Cons (a, b, c, d) (zip4 as bs cs ds)
{-@ reflect foldr @-}
foldr :: (a -> b -> b) -> b -> List a -> b
foldr _ z Nil = z
foldr f z (Cons x xs) = f x (foldr f z xs)