packages feed

safe-coupling-0.1.0.0: src/Data/List.hs

{-@ 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)