You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
haskell/04-types-and-typeclasses.hs

87 lines
2.3 KiB

-- 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