Created
April 13, 2017 07:15
-
-
Save dtoma/b4100dcca9248f6314c6c6f4953675ef to your computer and use it in GitHub Desktop.
A gentle introduction to haskell 98
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- A gentle introduction to Haskell 98 | |
import Test.QuickCheck | |
import Data.List | |
---------------------------------------------- | |
-- Chapter 2: Values, Types, and Other Goodies | |
data Tree a = Leaf a | Branch (Tree a) (Tree a) | |
fringe :: Tree a -> [a] | |
fringe (Leaf x) = [x] | |
fringe (Branch left right) = fringe left ++ fringe right | |
-- ghci> t = Branch (Leaf 1) (Branch (Leaf 2) (Leaf 3)) | |
-- ghci> fringe t | |
-- [1,2,3] | |
simple_compr = [(+1) x | x <- [1,2,3,4]] | |
-- [2,3,4,5] | |
nested_compr = [(x,y) | x <- [1,2,3,4], y <- [5,6,7,8]] | |
-- [(1,5),(1,6),(1,7),(1,8), | |
-- (2,5),(2,6),(2,7),(2,8), | |
-- (3,5),(3,6),(3,7),(3,8), | |
-- (4,5),(4,6),(4,7),(4,8)] | |
quicksort [] = [] | |
quicksort (x:xs) = quicksort [y | y <- xs, y < x] | |
++ [x] | |
++ quicksort [y | y <- xs, y >= x] | |
-- ghci> quickCheck(\xs -> quicksort xs == sort xs) | |
-- +++ OK, passed 100 tests. | |
some_list = [1,3..10] | |
-- [1,3,5,7,9] | |
hello_world = "hello" ++ " world" | |
-- "hello world" | |
----------------------- | |
-- Chapter 3: Functions | |
fib = 1 : 1 : [a + b | (a,b) <- zip fib (tail fib)] | |
-- ghci> take 5 fib | |
-- [1,1,2,3,5] | |
--------------------------------------------------- | |
-- Chapter 4: Case Expressions and Pattern Matching | |
-- duplicate_first_element (x:xs) = x:x:xs | |
duplicate_first_element s@(x:xs) = x:s | |
-- ghci > duplicate_first_element [1,2,3,4] | |
-- [1,1,2,3,4] | |
sign x | x > 0 = 1 | |
| x == 0 = 0 | |
| x < 0 = -1 | |
-- ghci> sign (-2) | |
-- -1 | |
-- pattern matching is defined in terms of case expressions | |
mtake m ys = case (m, ys) of | |
(0, _) -> [] | |
(_, []) -> [] | |
(n, x:xs) -> x : mtake (n - 1) xs | |
-- ghci> mtake 2 [1,2,3,4] | |
-- [1,2] | |
-- Here if we remove the ~, the computation is stuck | |
-- ~ makes it a lazy pattern which immediately succeeds and lets the computation start | |
client cinit ~(resp:resps) = cinit : client (next resp) resps | |
server (req:reqs) = process req : server reqs | |
cinit = 0 | |
next resp = resp | |
process req = req + 1 | |
reqs = client cinit resps | |
resps = server reqs | |
-- ghci > take 10 reqs | |
-- [0,1,2,3,4,5,6,7,8,9] | |
-- Pattern bindings have an implicit ~ in front of them | |
fib2@(1:tfib) = 1 : 1 : [a + b | (a, b) <- zip fib2 tfib] | |
-- ghci> take 5 fib | |
-- [1,1,2,3,5] | |
------------------------------------------ | |
-- Chapter 5: Type Classes and Overloading | |
-------------------------- | |
-- Chapter 6: Types, Again | |
newtype Natural = MakeNatural Integer | |
toNatural :: Integer -> Natural | |
toNatural x | x < 0 = error "Can't create negative naturals!" | |
| otherwise = MakeNatural x | |
fromNatural :: Natural -> Integer | |
fromNatural (MakeNatural i) = i | |
instance Num Natural where | |
fromInteger = toNatural | |
x + y = toNatural (fromNatural x + fromNatural y) | |
x * y = toNatural (fromNatural x * fromNatural y) | |
x - y = let r = fromNatural x - fromNatural y in | |
if r < 0 then error "Unnatural substraction" | |
else toNatural r | |
-- Could do: | |
-- data Point = Pt Float Float | |
-- pointx :: Point -> Float | |
-- pointx (Pt x _) = x | |
-- But we can also do: | |
data Point = Pt { pointx, pointy :: Float } | |
-- Could do: | |
-- absPoint :: Point -> Float | |
-- absPoint p = sqrt (pointx p * pointx p + | |
-- pointy p * pointy p) | |
-- But we can also do: | |
absPoint :: Point -> Float | |
absPoint (Pt { pointx = x, pointy = y }) = sqrt (x*x + y*y) | |
--------------- | |
-- Input/Output |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment