Haskell
Table of Contents
.hs
Stems from lambda calculus, with the lower details, such as integers, boolean, …, left to the compiler.
All functions are Pure Function, function as in mathmetical functions, and declarative. it does not care about the order of lines.
1. Syntax
1.1. Definition
Function
square :: Num a => a -> a -- define types
square x = x * x -- define operations
\x y -> x + y -- anonymous function. '\' because it looks like 'λ'
as-pattern (or alias pattern) can be used when defining a function on a data structure
printAge u@(User name age) = do
putStrLn ("The user's age is " ++ show age)
saveUserToDatabase u -- 'u' is bound to (User name age)
where and let-in keywords
magnitude x y = z where
z = sqrt (x*x + y*y)
Tuple
p1 :: (Float, Float, Float)
p1 = (1.0, 2.0, 1.0)
Data Type (Struct)
data Point3D = Point Float Float Float
data List a = L a (List a) | Empty -- With generic type a
A data type Point3D can be constructed by the constructor function Point.
There is an alternative way to define a data type called record syntax
data Person = Person
{ firstName :: String
, lastName :: String
, age :: Int
}
alex = Person { firstName = "Alex", lastName = "Smith", age = 28 }
main = putStrLn (firstName alex) -- the member access functions are auto-generated
olderAlex = alex { age = 29 } -- update is done incrementally
1.2. Branching
if-else statement
x = if condition then this else that
Pattern matching
fib :: Num a => a -> a
fib 0 = 1
fib 1 = 1
fib n = fib (n-2) + fib (n-1)
case-of statement
case a of
1 -> this
2 -> that
_ -> exit
Guarding
sign x
| x >= 0 = 1
| x < 0 = -1
| otherwise = 0
1.3. List
In haskell, there only exist linked lists.
Definition
list = [1, 2, 3]
list = 1:(2:(3:[]))
where : (cons) represents the operation of joining two
Indexing
x = [1, 2, 3] !! 0 -- 1
A range can be expressed easily with
[1..10000]
1.4. Recursion
Because of its functional nature, haskell only supports recursion rather than iteration. It's not a problem because every iteration can be expressed in recursion, and in terms of handling call stack, Haskell does its best to optimize it.
Recursion can be done by destructuring a list
sum :: [Int] -> Int
sum (x:xs) = x + sum xs
1.5. Evaluation
Function can be prefixed or infixed
elem 3 [1, 2, 3]
3 `elem` [1, 2, 3] -- prefix to infix
3 + 5
(+) 3 5 -- infix to prefix
Composition
(.) :: (b -> c) -> (a -> b) -> (a -> c)
(f . g) x = f (g x)
This is useful when composing function before the arguments are given.
Apply
($) :: (a -> b) -> a -> b
f $ x = f x
f :: Int -> Int -> Int
f a b = a + b
g :: Int -> Int
g = f 1 -- curried
2. Functions
Arithmetics
- =const
- forall a b. a -> b -> a=
List
- =head
- [a] -> a=
- =tail
- [a] -> [a]=
- =length
- [a] -> Int=
- =reverse
- [a] -> [a]=
- Notice
reverse xs = foldl (\acc x -> x : acc) [] xs
- Notice
- =take
- forall a. Int -> [a] -> [a]=
- =takeWhile
- forall a. (a -> Bool) -> [a] -> [a]=
- =drop
- forall a. Int -> [a] -> [a]=
- =dropWhile
- forall a. (a -> Bool) -> [a] -> [a]=
- =scanl
- (b -> a -> b) -> b -> [a] -> [b]=
- =foldl
- (b -> a -> b) -> b -> [a] -> b= nest operations to the left, calculate from the left
- Example:
foldl f z [1, 2, 3] = f (foldl f z [1, 2]) 3 - Use =foldl' :: (b -> a -> b) -> b -> [a] -> b= for eager evaluation
- Example:
- =map
- (a -> b) -> [a] -> [b]=
- Notice
map f xs = foldr (\x acc -> f x : acc) [] xs
- Notice
- =filter
- (a -> Bool) -> [a] -> [a]=
- Notice
filter p xs = foldr (\x acc -> if p x then x : acc else acc) [] xs
- Notice
Function
- =map
- Functor f
> (a -> b) -> f a -> f b
IO
- =show
- forall a. Show a
> a -> String
3. Monad
See monad
Bind
(>>=) :: Monad m => m a -> (a -> m b) -> m b
It corresponds to flatMap in other languages
>> :: Monad m => m a -> m b -> m b can be used when the first value is being discarded.
Join
join :: Monad m => m (m a) -> m a
3.1. Maybe Monad
Maybe type constructor
Maybe a = Just a | Nothing
r :: a -> Maybe a -- return
r x = Just x
f :: a -> Maybe b
g :: b -> Maybe c
-- f g
-- [\a -> Maybe b] [\b -> Maybe c]
-- \a -> [Maybe b >>= \b -> Maybe c]
-- >>= :: Maybe b -> (b -> Maybe c) -> Maybe c
Maybe a >>= g = case Maybe a of
Nothing -> Nothing
Just b -> g b
3.2. IO Manad
takes "world" as input and produces another "world" as an output
main :: IO ()
main = do
input <- getLine -- () -> IO(String)
writeFile "result.txt" (map toUpper input) -- Path -> String -> IO()
4. Packages
Module can be defined with
module Module
( f1, f2, f3 ) where
f1 :: ...
f2 :: ...
f3 :: ...
and imported in other file with
import Module
import Module (f1, f2)
import qualified Module as Mod
a = f1
c = Mod.f3
A type can be imported with all-inclusive wildcard so that all of its constructors and fields are imported alongside
import Data.Maybe (Maybe(..))
-- Just, Nothing are also imported
The packages are stored in /usr/lib/ghc-N.N.N/site-local/ in the
form of *.dyn_hi
4.1. System.IO
- =getLine
- IO String=
- =putStr
- String -> IO ()= write to standard out
4.2. Data.Bits
(.|.)Bitwise OR
5. Compiler
ghc: The Glasgow Haskell Compiler-dynamicuse dynamic linking. Use this if Haskell is installed as shared library, for example on Arch.
ghc-staticcompile using static linkingghc-libsdynamic libraries