87 lines
2.3 KiB
Haskell
Executable File
87 lines
2.3 KiB
Haskell
Executable File
-- in GHCi, we can use :t to get the type of something
|
|
|
|
-- :t "Hello!"
|
|
"Hello!" :: [Char]
|
|
|
|
-- It's good practice to give functions type declarations
|
|
|
|
removeNonUppercase :: String -> String
|
|
removeNonUppercase st = [c | c <- st, c `elem` ['A'..'Z']]
|
|
|
|
addThree :: Int -> Int -> Int -> Int
|
|
addThree x y z = x + y + z
|
|
|
|
-- Common types:
|
|
-- Int - normal integer
|
|
-- Integer - big integer, less efficient
|
|
-- Float - real floating point, single precision
|
|
-- Double - real floating point, double precision
|
|
-- Bool - True or False
|
|
-- Char - single character
|
|
|
|
-- Type variables - write polymorphic functions that don't use the type-specific
|
|
-- features of the values passed in:
|
|
|
|
-- :t fst
|
|
fst :: (a,b) -> a
|
|
|
|
-- :t head
|
|
head :: [a] -> a
|
|
|
|
-- `a` is the type-variable here
|
|
|
|
-- => denotes a class constraint. e.g. :t (==)
|
|
(==) :: (Eq a) => a -> a -> Bool
|
|
|
|
-- This says (==) takes a and a to Bool, given that the a's are members of the Eq class
|
|
-- Another example:
|
|
|
|
-- :t elem
|
|
elem :: (Eq a) => a -> [a] -> Bool
|
|
|
|
-- Eq - classes support equality testing
|
|
-- Ord - types have an ordering
|
|
|
|
-- e.g. :t (>)
|
|
(>) :: (Ord a) => a -> a -> Bool
|
|
|
|
-- To be a member of Ord, you must be a member of Eq and have defined behavior for the `compare` function.
|
|
|
|
-- Show - members can be presented as strings
|
|
-- Read - opposite of show - takes a string and returns a type that is a member of Read
|
|
|
|
-- e.g.
|
|
restTest1 = read "[1,2,3,4]" ++ [3] -- == [1,2,3,4,3]
|
|
|
|
-- The way the result of `read` is used determines what typeclass the value is instanced in
|
|
-- :t read
|
|
read :: (Read a) => String -> a
|
|
|
|
-- the `a` variable is determined by the usage. We can be explicit:
|
|
readTest2 = read "5" :: Int -- a is Int
|
|
|
|
-- Enum - sequential types that can be enumerated - Enum types can be used in list ranges
|
|
-- Bounded - have upper and lower bounds
|
|
|
|
-- e.g.
|
|
minBoundTest1 = minBound :: Int
|
|
maxBoundTest1 = maxBound :: Char
|
|
|
|
-- these have type (Bounded a) => a - essentially polymorphic constants
|
|
-- the value changes depending on the typecast
|
|
|
|
-- Num - members can act like numbers, e.g.
|
|
|
|
-- :t 20
|
|
20 :: (Num t) => t
|
|
|
|
-- :t (*)
|
|
(*) :: (Num a) => a -> a -> a
|
|
|
|
-- Integral - only whole numbers - superset including Int and Integer
|
|
-- Floating - only floating point numbers - Float and Double
|
|
|
|
-- Useful note: fromIntegral takes an Integral to a generic Num type
|
|
-- :t fromIntegral
|
|
fromIntegral :: (Num b, Integral a) => a -> b
|