module Prelude.Week0 (
  -- * Basic Types
  Char, String, Int, Double, Bool(True, False),

  -- * Arithmetic arithmetic and comparison
  -- ** Integer arithmetic and comparison
  (+), (-), (*), mod, (>), (<), (>=), (<=), (==), (/=),

  -- ** Double arithmetic and comparison
  (+.), (-.), (*.), (>.), (<.), (>=.), (<=.), (==.), (/=.),

  -- ** Boolean operators
  (||), (&&), not,

  -- * Type conversion functions
  doubleToString, intToString, charToString, intToDouble, intToChar, charToInt,

  -- * Very basic lists
  BasicList, empty, prepend, get,

  -- * String operations
  (<>),

  -- * Other convenient operators
  (.), trace, P.error,

  -- * Output
  print,

  -- * Ignore these
  (>>), return,
  ) where

import qualified Prelude as P
import qualified Data.Char
import Prelude (fmap, map, (>>), (>>=), return, putStrLn, getLine, readFile, ($), print, (.), mapM, (||), (&&), not, Bool(..))

import Debug.Trace (trace)

type Int = P.Int
type Double = P.Double
type IO  = P.IO
type Char = P.Char
type String = [P.Char]

-- Integer arithmetic

(+) :: Int -> Int -> Int
(+) = (P.+)

(-) :: Int -> Int -> Int
(-) = (P.-)

(*) :: Int -> Int -> Int
(*) = (P.*)

mod :: Int -> Int -> Int
mod = P.mod

-- Floating point arithmetic

(+.) :: Double -> Double -> Double
(+.) = (P.+)

(-.) :: Double -> Double -> Double
(-.) = (P.-)

(*.) :: Double -> Double -> Double
(*.) = (P.*)

(/.) :: Double -> Double -> Double
(/.) = (P./)

-- String operations
-- | Append two strings.
(<>) :: String -> String -> String
(<>) = (P.++)

-- Conversion functions
doubleToString :: Double -> String
doubleToString = P.show

intToString :: Int -> String
intToString = P.show

charToString :: Char -> String
charToString = P.show

intToDouble :: Int -> Double
intToDouble = P.fromIntegral

intToChar :: Int -> Char
intToChar = Data.Char.chr

charToInt :: Char -> Int
charToInt = Data.Char.ord

-- Comparison
(==) :: Int -> Int -> Bool
(==) = (P.==)

(==.) :: Double -> Double -> Bool
(==.) = (P.==)

(<=) :: Int -> Int -> Bool
(<=) = (P.<=)

(<=.) :: Double -> Double -> Bool
(<=.) = (P.<=)

(>=) :: Int -> Int -> Bool
(>=) = (P.>=)

(>=.) :: Double -> Double -> Bool
(>=.) = (P.>=)

(<) :: Int -> Int -> Bool
(<) = (P.<)

(<.) :: Double -> Double -> Bool
(<.) = (P.<)

(>) :: Int -> Int -> Bool
(>) = (P.>)

(>.) :: Double -> Double -> Bool
(>.) = (P.>)

(/=) :: Int -> Int -> Bool
(/=) = (P./=)

(/=.) :: Double -> Double -> Bool
(/=.) = (P./=)

-- Basic lists
newtype BasicList a = BasicList {unBasic :: [a] }

empty :: BasicList a
empty = BasicList []

prepend :: a -> BasicList a -> BasicList a
prepend x (BasicList xs) = BasicList (x : xs)

get :: Int -> BasicList a -> a
get idx (BasicList xs) = xs P.!! idx