{- The overloaded Standard Prelude for the Helium Compiler -} module Prelude where import PreludePrim infixr 9 . infixl 9 !! infixr 8 ^ -- , **. -- infixl 7 *, `quot`, `rem`, `div`, `mod`, / [PreludePrim] -- infixl 6 +, - [PreludePrim] infixr 5 ++ -- infixr 5 : [HeliumLang] -- infix 4 ==, /=, <=, <, >, >= [PreludePrim] infixr 3 && infixr 2 || infixr 0 $ --, $! [PreludePrim] {----------------------------------------------- -- Num -----------------------------------------------} {- imported from PreludePrim (+) :: Num a => a -> a -> a (-) :: Num a => a -> a -> a (*) :: Num a => a -> a -> a negate :: Num a => a -> a fromInt :: Num a => Int -> a -} sum :: Num a => [a] -> a sum = foldl' (+) (fromInt 0) product :: Num a => [a] -> a product = foldl' (*) (fromInt 1) {----------------------------------------------- -- Eq -----------------------------------------------} {- imported from PreludePrim (==) :: Eq a => a -> a -> Bool (/=) :: Eq a => a -> a -> Bool -} elem :: Eq a => a -> [a] -> Bool elem _ [] = False elem x (y:ys) | x == y = True | otherwise = elem x ys notElem :: Eq a => a -> [a] -> Bool notElem x ys = not (x `elem` ys) lookup :: Eq a => a -> [(a,b)] -> Maybe b lookup _ [] = Nothing lookup k ((x,y):xys) | k == x = Just y | otherwise = lookup k xys {----------------------------------------------- -- Ord -----------------------------------------------} {- imported from PreludePrim (<) :: Ord a => a -> a -> Bool (<=) :: Ord a => a -> a -> Bool (>) :: Ord a => a -> a -> Bool (>=) :: Ord a => a -> a -> Bool compare :: Ord a => a -> a -> Ordering -} max :: Ord a => a -> a -> a max x y = if x < y then y else x min :: Ord a => a -> a -> a min x y = if x < y then x else y maximum :: Ord a => [a] -> a maximum = foldl1 max minimum :: Ord a => [a] -> a minimum = foldl1 min {----------------------------------------------- -- Enum -----------------------------------------------} {- imported from PreludePrim succ :: Enum a => a -> a pred :: Enum a => a -> a enumFromTo :: Enum a => a -> a -> [a] enumFromThenTo :: Enum a => a -> a -> a -> [a] toEnum :: Enum a => Int -> a fromEnum :: Enum a => a -> Int enumFrom :: Enum a => a -> [a] enumFromThen :: Enum a => a -> a -> [a] -} {----------------------------------------------- -- Int -----------------------------------------------} {- imported from PreludePrim rem :: Int -> Int -> Int div :: Int -> Int -> Int mod :: Int -> Int -> Int quot :: Int -> Int -> Int -} -- for compatibility with Haskell textbooks type Integer = Int abs :: Int -> Int abs x = if x < 0 then - x else x signum :: Int -> Int signum x = case compare x 0 of LT -> -1 EQ -> 0 GT -> 1 even :: Int -> Bool even n = n `rem` 2 == 0 odd :: Int -> Bool odd n = not (even n) subtract :: Int -> Int -> Int subtract a b = b - a gcd :: Int -> Int -> Int gcd 0 0 = error "Prelude.gcd: gcd 0 0 is undefined" gcd x y = gcd' (abs x) (abs y) where gcd' :: Int -> Int -> Int gcd' x' 0 = x' gcd' x' y' = gcd' y' (x' `rem` y') lcm :: Int -> Int -> Int lcm _ 0 = 0 lcm 0 _ = 0 lcm x y = abs ((x `quot` gcd x y) * y) (^) :: Num a => a -> Int -> a _ ^ 0 = fromInt 1 i ^ n | n > 0 = f i (n-1) i | otherwise = error "Prelude.^: negative exponent" where f _ 0 y = y f x m y = g x m where g x' m' | even m' = g (x' * x') (m' `quot` 2) | otherwise = f x' (m' - 1) (x' * y) {----------------------------------------------- -- Float -----------------------------------------------} {- imported from PreludePrim (/) :: Float -> Float -> Float sqrt :: Float -> Float (**.) :: Float -> Float -> Float exp :: Float -> Float log :: Float -> Float sin :: Float -> Float cos :: Float -> Float tan :: Float -> Float -} absFloat :: Float -> Float absFloat x = if x < 0.0 then (-. x) else x signumFloat :: Float -> Int signumFloat x = case compare x 0.0 of LT -> -1 EQ -> 0 GT -> 1 pi :: Float pi = 3.141592653589793 {----------------------------------------------- -- Bool -----------------------------------------------} not :: Bool -> Bool not False = True not _ = False (||) :: Bool -> Bool -> Bool (&&) :: Bool -> Bool -> Bool x || y = if x then x else y x && y = if x then y else x otherwise :: Bool otherwise = True {----------------------------------------------- -- Maybe -----------------------------------------------} data Maybe a = Nothing | Just a deriving (Eq, Show) maybe :: b -> (a -> b) -> Maybe a -> b maybe e f m = case m of Nothing -> e Just x -> f x {----------------------------------------------- -- Either -----------------------------------------------} data Either a b = Left a | Right b deriving (Eq, Show) either :: (a -> c) -> (b -> c) -> Either a b -> c either l r e = case e of Left x -> l x Right y -> r y {----------------------------------------------- -- Ordering -----------------------------------------------} {- imported from PreludePrim data Ordering = LT | EQ | GT -} {----------------------------------------------- -- Tuple -----------------------------------------------} fst :: (a, b) -> a fst (x, _) = x snd :: (a, b) -> b snd (_, x) = x curry :: ((a,b) -> c) -> (a -> b -> c) curry f x y = f (x,y) uncurry :: (a -> b -> c) -> ((a,b) -> c) uncurry f p = f (fst p) (snd p) zip :: [a] -> [b] -> [(a,b)] zip = zipWith (\a b -> (a,b)) zip3 :: [a] -> [b] -> [c] -> [(a,b,c)] zip3 = zipWith3 (\a b c -> (a,b,c)) zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] zipWith z (a:as) (b:bs) = z a b : zipWith z as bs zipWith _ _ _ = [] zipWith3 :: (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d] zipWith3 z (a:as) (b:bs) (c:cs) = z a b c : zipWith3 z as bs cs zipWith3 _ _ _ _ = [] unzip :: [(a,b)] -> ([a],[b]) unzip = foldr (\(a,b) (as,bs) -> (a:as, b:bs)) ([], []) unzip3:: [(a,b,c)] -> ([a],[b],[c]) unzip3 = foldr (\(a,b,c) (as,bs,cs) -> (a:as,b:bs,c:cs)) ([],[],[]) {----------------------------------------------- -- List -----------------------------------------------} -- We can't import Char here because that would mean we couldn't import -- it elsewhere. Therefore, we make local copies of the two functions -- from that module localIsSpace :: Char -> Bool localIsSpace c = i == primOrd ' ' || i == primOrd '\t' || i == primOrd '\n' || i == primOrd '\r' || i == primOrd '\f' || i == primOrd '\v' where i = primOrd c localIsDigit :: Char -> Bool localIsDigit c = primOrd c >= primOrd '0' && primOrd c <= primOrd '9' {----------------------------------------------- -- List -----------------------------------------------} head :: [a] -> a head (x:_) = x head _ = error "Prelude.head: empty list" last :: [a] -> a last [x] = x last (_:xs) = last xs last _ = error "Prelude.last: empty list" tail :: [a] -> [a] tail (_:xs) = xs tail _ = error "Prelude.tail: empty list" init :: [a] -> [a] init [_] = [] init (x:xs) = x : init xs init _ = error "Prelude.init: empty list" null :: [a] -> Bool null [] = True null _ = False (++) :: [a] -> [a] -> [a] (x:xs) ++ ys = x : (xs ++ ys) [] ++ ys = ys map :: (a -> b) -> [a] -> [b] map _ [] = [] map f (x:xs) = f x : map f xs filter :: (a -> Bool) -> [a] -> [a] filter p (x:xs) | p x = x : filter p xs | otherwise = filter p xs filter _ [] = [] {- Naive implementation of length (slow because of laziness) length :: [a] -> Int length [] = 0 length (_:xs) = 1 + length xs Optimised implementation using strict foldl: -} length :: [a] -> Int length xs = foldl' (\l _ -> l + 1) 0 xs concat :: [[a]] -> [a] concat = foldr (++) [] (!!) :: [a] -> Int -> a xs !! n | n < 0 = error "Prelude.(!!): negative index" | null xs = error "Prelude.(!!): index too large" | n == 0 = head xs | otherwise = tail xs !! (n - 1) foldl :: (a -> b -> a) -> a -> [b] -> a foldl _ z [] = z foldl f z (x:xs) = foldl f (f z x) xs foldl' :: (a -> b -> a) -> a -> [b] -> a foldl' _ a [] = a foldl' f a (x:xs) = (foldl' f $! f a x) xs foldl1 :: (a -> a -> a) -> [a] -> a foldl1 f (x:xs) = foldl f x xs foldl1 _ [] = error "Prelude.foldl1: empty list" scanl :: (a -> b -> a) -> a -> [b] -> [a] scanl f q xs = q : ( case xs of [] -> [] y:ys -> scanl f (f q y) ys ) scanl1 :: (a -> a -> a) -> [a] -> [a] scanl1 _ [] = [] scanl1 f (x:xs) = scanl f x xs foldr :: (a -> b -> b) -> b -> [a] -> b foldr _ z [] = z foldr f z (x:xs) = f x (foldr f z xs) foldr1 :: (a -> a -> a) -> [a] -> a foldr1 _ [x] = x foldr1 f (x:xs) = f x (foldr1 f xs) foldr1 _ [] = error "Prelude.foldr1: empty list" scanr :: (a -> b -> b) -> b -> [a] -> [b] scanr _ q0 [] = [q0] scanr f q0 (x:xs) = case scanr f q0 xs of qs@(q:_) -> f x q : qs _ -> error "Prelude.scanr" scanr1 :: (a -> a -> a) -> [a] -> [a] scanr1 _ [] = [] scanr1 _ [x] = [x] scanr1 f (x:xs) = case scanr1 f xs of qs@(q:_) -> f x q : qs _ -> error "Prelude.scanr" iterate :: (a -> a) -> a -> [a] iterate f x = x : iterate f (f x) repeat :: a -> [a] repeat x = xs where xs = x:xs replicate :: Int -> a -> [a] replicate n x = take n (repeat x) cycle :: [a] -> [a] cycle [] = error "Prelude.cycle: empty list" cycle xs = xs' where xs'=xs++xs' take :: Int -> [a] -> [a] take n xs | n <= 0 = [] | otherwise = case xs of [] -> [] (y:ys) -> y : take (n-1) ys drop :: Int -> [a] -> [a] drop n xs | n <= 0 = xs | otherwise = case xs of [] -> [] (_:ys) -> drop (n-1) ys splitAt :: Int -> [a] -> ([a], [a]) splitAt n xs | n <= 0 = ([],xs) | otherwise = case xs of [] -> ([],[]) (y:ys) -> (y:as,bs) where (as,bs) = splitAt (n-1) ys takeWhile :: (a -> Bool) -> [a] -> [a] takeWhile _ [] = [] takeWhile p (x:xs) | p x = x : takeWhile p xs | otherwise = [] dropWhile :: (a -> Bool) -> [a] -> [a] dropWhile _ [] = [] dropWhile p l@(x:xs) | p x = dropWhile p xs | otherwise = l span :: (a -> Bool) -> [a] -> ([a],[a]) span _ [] = ([],[]) span p xs@(x:xs') | p x = (x:ys, zs) | otherwise = ([],xs) where (ys,zs) = span p xs' break :: (a -> Bool) -> [a] -> ([a],[a]) break p = span (not . p) lines :: String -> [String] lines "" = [] lines s = let l,s' :: String (l,s') = break (\x -> x == '\n') s in l : case s' of [] -> [] (_:s'') -> lines s'' words :: String -> [String] words s = case dropWhile localIsSpace s of "" -> [] s' -> w : words s'' where w,s'' :: String (w,s'') = break localIsSpace s' unlines :: [String] -> String unlines [] = [] unlines (l:ls) = l ++ '\n' : unlines ls unwords :: [String] -> String unwords [] = "" unwords [w] = w unwords (w:ws) = w ++ ' ' : unwords ws reverse :: [a] -> [a] reverse = foldl (flip (:)) [] and :: [Bool] -> Bool and = foldr (&&) True or :: [Bool] -> Bool or = foldr (||) False any :: (a -> Bool) -> [a] -> Bool any p = or . map p all :: (a -> Bool) -> [a] -> Bool all p = and . map p concatMap :: (a -> [b]) -> [a] -> [b] concatMap f = concat . map f {----------------------------------------------- -- Conversion -----------------------------------------------} -- see also "read.." and "show.." below {- imported from PreludePrim primOrd :: Char -> Int primChr :: Int -> Char intToFloat :: Int -> Float round :: Float -> Int floor :: Float -> Int ceiling :: Float -> Int truncate :: Float -> Int -} {----------------------------------------------- -- Some standard functions -----------------------------------------------} fix :: (a -> a) -> a fix f = x where x = f x id :: a -> a id x = x const :: a -> b -> a const x _ = x (.) :: (b -> c) -> (a -> b) -> (a -> c) (.) f g x = f (g x) flip :: (a -> b -> c) -> b -> a -> c flip f x y = f y x ($) :: (a -> b) -> a -> b f $ x = f x {- imported from PreludePrim seq :: a -> b -> b ($!) :: (a -> b) -> a -> b error :: String -> a -} until :: (a -> Bool) -> (a -> a) -> a -> a until p f x = if p x then x else until p f (f x) undefined :: a undefined = error "undefined" {----------------------------------------------- -- IO -----------------------------------------------} (>>=) :: IO a -> (a -> IO b) -> IO b (>>=) io f = do x <- io f x (>>) :: IO a -> IO b -> IO b p >> q = p >>= \ _ -> q {- imported from PreludePrim return :: a -> IO a putChar :: Char -> IO () putChar c = primPutChar c putStr :: String -> IO () putStr s = primPutStr s putStrLn :: String -> IO () putStrLn s = primPutStrLn s unsafePerformIO :: IO a -> a unsafePerformIO = primUnsafePerformIO -} sequence_ :: [IO a] -> IO () sequence_ = foldr (>>) (return ()) print :: Show a => a -> IO () print e = putStrLn (show e) getLine :: IO String getLine = do c <- getChar if c == '\n' then return "" else do cs <- getLine return (c:cs) writeFile :: String -> String -> IO () writeFile fname s = bracketIO (openFile fname WriteMode) (hClose) (\h -> hPutString h s) readFile :: String -> IO String readFile fname = bracketIO (openFile fname ReadMode) (hClose) (\h -> readAll h []) where readAll h acc = do c <- hGetChar h readAll h (c:acc) `catchEof` (return (reverse acc)) bracketIO :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c bracketIO acquire release action = do x <- acquire finallyIO (action x) (release x) finallyIO :: IO a -> IO b -> IO a finallyIO io action = do x <- io `catch` (\exn -> do{ action; raise exn }) action return x {----------------------------------------------- -- Read -----------------------------------------------} readInt :: String -> Int readInt [] = 0 readInt ('-':s) = - readUnsigned s readInt s = readUnsigned s readUnsigned :: String -> Int readUnsigned = foldl (\a b -> a * 10 + b) 0 . map (\c -> primOrd c - primOrd '0') . takeWhile localIsDigit