Skip to content

Instantly share code, notes, and snippets.

@dtoma
Created April 13, 2017 07:15
Show Gist options
  • Save dtoma/b4100dcca9248f6314c6c6f4953675ef to your computer and use it in GitHub Desktop.
Save dtoma/b4100dcca9248f6314c6c6f4953675ef to your computer and use it in GitHub Desktop.
A gentle introduction to haskell 98
-- 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