Haskell - Introduction
I have spent the past 4-6 months playing with Haskell on the side. While I've yet come to the conclusion that one paradigm of programming is inherently better than the other, I have at least found it very intellectually rewarding and exciting to take a step back, and try to implement algorithms, data structures, and other hackings using a functional programmer's mindset. I can't say that I've fully grasped everything but I imagine it's just a function of time.
First, I highly recommend the following book: "Learn You a Haskell for Great Good"
I uploaded most of my Haskell examples to GitHub, found here
I chose a few random examples to demonstrate some of the cool examples that made me enjoy Haskell
Simple Functions
f x y = x*x + y*y -- simple function of x and y
g y = f 0 Y -- partial solved function
h :: Int -> Int -> Int -- typed function
h x y = x*x + y*y
i :: Num a => a -> a-> a -- any Numeric type
i x y = x*x + y*y
main = do
print (f 2 3)
print (g 3)
print (h 2 3)
-- (h 2.3 4.2) would fail
print (i 2 3.4)
Folding
main = do
print (foldl (+) 0 [1, 2, 3]) -- summation using foldl
Use of Gaurds to create Piecewise Functions:
guess x
| x > 27 = "Too high!"
| x < 27 = "Too low!"
| otherwise = "Correct!"
main = do
print (guess 100)
print (guess 0)
print (guess 27)
Filters:
main = do
print (filter even [1..10])
print (filter (>5) [1..10])
List Comprehensions, ∀x∈S, p(x):
-- ∀x∈S, p(x)
-- [ x | x <- s, p x ]
p = [ x+5 | x <- [1,2,3] ]
f x y = x + y
main = do
print p
print ([ x+5 | x <- [1,2,3] ])
print ([ x | x <- [2..10], 10 `mod` x == 0])
print ([ team ++ " " ++ player |
team <- ["red", "blue"],
player <- ["soldier", "pyro", "scout"] ])
print ([ x | x<-[1..10], even x ])
print ([ f x y
| x <- [1..10]
, y <- [1..10]])
Function Composition:
main = do
-- f(g(h(k(x)))) - ugly
-- (f.g.h.k)(x) - pretty
print ((not.odd) 4)
print ((length.head.words) "University of Arkansas")
let f x = 2 * x + 3
let g x = x * x
let h x = sin x
print ((f.g.h) 3)
print (f (g (h 3)))
Function Examples using Let and Where:
slope (x1,y1) (x2,y2) = let dy = y2-y1
dx = x2-x1
in dy/dx
slope2 (x1,y1) (x2,y2) = dy/dx
where dy = y2-y1
dx = x2-x1
slope3 (x1,y1) (x2,y2) = (y2 - y1) / (x2 - x1)
main = do
print (slope (1,1) (2,2))
print (slope2 (1,1) (2,2))
print (slope (1,3) (10,4))
print (slope (-1,1) (0, 0))
Fibonacci Sequence Implementations:
-- simple, naive implementation
slow_fib :: Int -> Integer
slow_fib 0 = 1
slow_fib 1 = 1
slow_fib n = slow_fib (n-2) + slow_fib (n-1)
-- a memoized version. The magic lies in the "map fib [0 ..]" which is
-- the fibonacci sequence mapped to an infinite list! ^_^ which is only
-- possible due to the lazy nature of Haskell.
memoized_fib :: Int -> Integer
memoized_fib = (map fib [0 ..] !!)
where fib 0 = 1
fib 1 = 1
fib n = memoized_fib (n-2) + memoized_fib (n-1)
Binary Tree:
This was my first attempt at implementing. I have since found more eloquent solutions :)
data Tree = Node { value::Int, left::Tree, right::Tree } | Null deriving (Show, Eq)
total :: Tree -> Int
total Null = 0
total node = value node + total (left node) + total(right node)
size :: Tree -> Int
size Null = 0
size node = 1 + size (left node) + size (right node)
add :: Int -> Tree -> Tree
add v Null = (Node v Null Null)
add v node
| v > (value node) = Node (value node) (left node) (add v (right node)) -- insert into right subtree
| v < (value node) = Node (value node) (add v (left node)) (right node) -- insert into left subtree
| otherwise = node -- value is(value node)new so add it
Fizz Buzz:
fizzbuzz x
| (mod x 15) == 0 = "FizzBuzz"
| (mod x 3) == 0 = "Fizz"
| (mod x 5) == 0 = "Buzz"
| otherwise = show x
main = print(map fizzbuzz [1..100])
PI Gregory Series:
piSum :: Int -> Double
piSum n = sum (map f [1..n])
f :: Int -> Double
f x = 4 * (-1)^(x+1) / (2*k - 1)
where k = fromIntegral x
main = do
print "pi sum 1"
print (piSum 1)
print (piSum 2)
print (piSum 5)
print (piSum 10)
print (piSum 100)
print (piSum 1000)
print (piSum 10000)
print (piSum 100000)
Quick Sort:
qsort [] = []
qsort (p:xs) = (qsort lesser) ++ [p] ++ (qsort greater)
where
lesser = filter (< p) xs
greater = filter (>= p) xs
main = print (qsort [20,3,14,6,1,10])
Triangles:
triangles n = [(a,b,c)
| c<-[1..n]
, b<-[1..c]
, a<-[1..b]
, a^2 + b^2 == c^2]
main = do
print (triangles 10)
print (triangles 15)
print (triangles 100)
Drop piece into Connect 4 Column:
numEmpty :: [Int] -> Int
numEmpty board = length $ filter (\x -> x == 0) board
addToColumn :: Int -> [Int] -> [Int]
addToColumn val board = xs ++ [val] ++ ys
where
n = (numEmpty board)
xs = replicate (n - 1) 0
ys = snd (splitAt n board)
-- simulate dropping a piece into a connect 4 board column
main = do
let board = [0,0,0,0,0,1,-1,1]
print board
print $ addToColumn 1 board
-- outputs [0,0,0,0,1,1,-1,1]
Utf8:
-- 値をゼロにする (utf8 comment works
f x = 0
e = exp 1
シグモイド :: Double -> Double
シグモイド x = 1 / (1 + e**(-x))
main = do
print (f 10)
print (シグモイド 0)