Cheatsheet.hs | |
---|---|
| |
These are some examples for haskell syntax with concise
explanations. If you are a real
fp ninja you might be able
to learn haskell by reading this, but it is targeted to haskell learners,
who read a tutorial or book like LYAH
and need a reference card to remember the syntax and some patterns.
You can load it into | {-
- This is a block comment.
-
- One line comments start with --
-} |
Module Definition | |
A module definition has a name andd optionally lists everything you want to export in braces. | module Cheatsheet |
Export types with a list of constructors or export all contructors. | ( Recsam(Recsam)
, Datasam(..) |
You can export all values and even reexport imports with | , datasam
, module Control.Monad
) where |
Imports | |
Imports load other modules into our scope. Sometimes you have to import submodules too. | import Control.Monad
import Control.Monad.Reader |
You can decide to only load some functions. Instances and typeclasses are loaded anyways. | import Data.Function (on) |
The | import qualified Data.Char as C (ord, chr)
import Prelude hiding (gcd) |
Typeclass | |
A class resembles interfaces and abstract classes of OOP. This one "extends" Num. Classes list the types of functions to provide using a type variable. Classes may include default implementations. | class (Num a) => Classam a where
classam :: a -> Bool
classam = const False |
Data | |
The data keyword allows definition of algebraic data types.
They can derive Datas can have type variables and be recursive. | data Datasam = A | B | C
deriving Show
data Datarecsam a = End a | Recur (Datarecsam a) |
You construct datas using their constructor functions. They can be used like normal functions. | datasam = A
datarecsam :: [Datarecsam Int]
datarecsam = Recur (End 2) : map (Recur . Recur . End) [3..5] |
You can make datas instances with a header similar
to the class definition.
You do not always have to define all methods.
With this definition we can print the above list like | instance Show a => Show (Datarecsam a) where
show (End x) = show x
show (Recur xs) = '>': show xs |
Record Syntax | |
The use of the record syntax ist defining algebraic data types giving meaningful names to their members. | data Recsam = Recsam { name :: String
, hidden :: Bool
} deriving Show |
Reocrd syntax enables easy constructing. Note the | recsam = Recsam { name = "Example", hidden = True } |
The fields of a record are at the same time getter functions. | recsamName = name recsam |
You can pattern match againts a record.
If you type | assertShown Recsam { hidden = True } = error "Not shown"
assertShown _ = () |
You can use records to build derivates.
If you type | recsam' = recsam { hidden = False } |
Newtype | |
Newtypes are similar to a type alias, they carry own instances
even using | newtype Ntsam = Ntsam [Int] |
Type | |
Type is another alias tool, but only creates a synonyme name and no constructors.
It's most prominent use is | type Pair a = (a,a) |
Note that you should avoid recursion. The following works however. | type Coords = Pair Int |
Special Function Syntax | |
There are some advanced function building methods. The examples demonstrate
referencing of an infix operator, building lambdas with | add a b = a + b
add' = (+)
add'' = \a b -> a+b
add3 a b = (+a) b
add4 a b = a `add3` b
a +# b = add a b
infixl 9 +# |
Pattern matching | |
There are pattern matchng examples for function definitions in the
sections about | patternsam x y =
let (a,b) = (,) x y
in case a of 3 -> b
(n+1) -> n |
You can pattern match tuples, lists and sums with their syntactic
sugar in adition to normal constructors. You can use the | single3 l@[3] = Just l
single3 _ = Nothing |
Let & where, if, case & guards | |
If you just want to check constructors use pattern matching, see above.
Sometimes you want to use complex predicates though. You can choose guards.
With a | numsam x
| x < 3 = phrase "small"
| x < 50 = phrase "medium"
| otherwise = phrase "huge"
where
phrase s = "A "++s++" number!" |
A little mothe flexible are | numsam' x
= let phrase s = "A "++s++" number!"
in case () of
_ | x < 3 -> phrase "small"
| x < 50 -> phrase "medium"
| otherwise -> phrase "huge" |
And of course there is | numsam'' x = phrase $
if x < 3 then "small"
else if x < 50 then "medium"
else "huge"
where phrase s = "A "++s++" number!" |
List comprehensions | |
An option for filtering and processing lists are list comprehensions. They take multiple input lists, predicates and an output expression. | listcmrsam = [(x,show y) | x <- [0..3], y <- [3..5], x*y < 4] |
Monads | |
The above list comprehension can be written in monadic style too. | monsam = [0..3] >>= (\x ->
[3..5] >>= (\y ->
guard (x*y < 4) >> return (x,show y) ) ) |
Do | |
When dealing with monads using the The first non whitespace char determines the width of indentation. | dosam = do
x <- [0..3]
y <- [3..5]
guard $ x*y < 4
return (x, show y) |
IO | |
The programm listed here defines a function Also interesting for simple I/O
are | main = do
times <- askNumber
sequence_ [putStrLn $ "line" ++ show n | n <- [0..times-1]]
askNumber :: IO Int
askNumber = do
putStrLn "How many?"
n <- readLn
if n>3 then return n
else do
print "To few!"
askNumber |
Pointfree Style | |
Here are some patterns for using pointfree style. | |
For comparing stuff use the | onsam x y = x*3 + y*3
onsam' = (+) `on` (*3) |
If you want to combine functions with arity one and two you can sometimes use the boobs operator. | (.:) = (.).(.)
(.:) :: (c -> d) -> (a -> b -> c) -> a -> b -> d |
Here's an example how to use the boobs operator with Y pipes: | ysam pe c pd= pe .: (c `on` pd) where
tapas = ysam ('T':) (++) ('a':) "p" "s" |
If you have two different pipes for one input and a combinator you use | liftM2sam pe c p1 p2 = pe . liftM2 c p1 p2
tapas' = liftM2sam (++"s") (++) ('T':) ('p':) "a" |
If you just want to clone an argument you can use join. | joinsam = join (+)
fiveDoubled = joinsam 5 |
If you have two different pipes for two different arguments and a combinator you use composition with a pre applyed function. | applysam c p1 p2 = (. p2) . c . p1
tacos = applysam (++) ("Ta"++) ('o':) "c" "s" |
Links | |
Here's some useful external references: | |
Meta | |
This file was written by Bernhard Häussner, you can find and fork the source at github and here's the annotated source code view processed by docco | |