Functional and speed. What do you define as speed? What kind of speed is important to you?
Comparison of F# and C# in the wild
public class CustomerName
{
public CustomerName(string firstName,
string middleInitial, string lastName)
{
this.FirstName = firstName;
this.MiddleInitial = middleInitial;
this.LastName = lastName;
}
public string FirstName { get; private set; }
public string MiddleInitial { get; private set; }
public string LastName { get; private set; }
}
type CustomerName(firstName, middleInitial, lastName) =
member this.FirstName = firstName
member this.MiddleInitial = middleInitial
member this.LastName = lastName
data CustomerName = CustomerName
{firstName :: Text
,middleInitial :: Text
,lastName :: Text }
What is interest? We'll start doing things in an additive way. More interested in data processing type things? Or maybe network?
- .hs
- .lhs
- ghci
- :info (:i)
- :type (:t)
- :r (reload)
- :load (load script name)
- :edit (uses editor)
- :? (list all commands)
- GHCI
- FP Complete
- What I Wish I Knew - try Text
- Functional Programming
- LYAH
- EdX
- Cheat Sheet
- Parallel and Concurrent Programming in Haskell
We use Λ or λ
λ > 2 + 15
λ > 59 * 100
λ > 5 / 2
λ > (-4) + 5
λ > True && False
False
λ > not (True && True)
False
λ > 5 == 5
True
λ > 5 /= 5
False
λ > "hello" == "hello"
λ > 5 == "hello"
ERROR!
- Bool
- Char
- String
- Int (fixed-precision)
- Integer (arbitrary-precision)
- Float
Expressions have a value, while statements do not. If you can pass it as an argument to a function, it's an expression. If you can't, it's a statement. Control flow constructs in C-derived languages are generally statements (you can't pass an 'if {}' block as a function parameter). Consequently, those languages tend to provide an expression form for 'if' (like the ternary operator). Of course, the whole point of many functional languages is that everything has a value, and that functions are first-class values, which means that everything is an expression. Statements usually appear in imperative languages, where you wish to write commands that don't necessarily return a value. - Lambda the Ultimate
- Operational semantics: Translates code to abstract machine statements
- Denotational semantics: Translates code to mathematical expressions
Ticks for infix, ' identify strict vs non.
echo "doubleMe x = x + x" > example.hs
ghci
λ > :l example.hs
λ > doubleSmall x = if x > 100 then x else x * 2
λ > conanO'Brien = "It's a-me, Conan O'Brien!"
λ > factorial n = product [1..n]
λ > average ns = sum ns `div` length ns
Almost everything in Haskell is a function, and every function can be prefix or infix:
λ > 1 + 1
λ > (+) 1 1
λ > min 9 10
λ > 9 `min` 10
λ > read "10" * 2
abs
mod
even
What is Prelude?
Functional is almost as much about lists as functions.
If you're indexing you're probably doing it wrong.
- head
- tail
- take
- drop
- length (O(n))
- sum
- product
- (++)
- reverse
rev [] = []
. . .
rev xs = last xs : rev (init xs)
rev xs = rev (tail xs) ++ [head xs]
rev (x:xs) = rev xs ++ [x]
Implement last
. . .
last xs = head ( drop (lengt xs - 1) xs) last xs = xs !! (length xs - 1)
> [x^2 | x <- [1..10]]
[1,4,9,16,25,36,49,64,81,100]
> [ odd x | x <- [1..9]]
[True,False,True,False,True,False,True,False,True]
Comprehensions with multiple generators, separated by commas. The generators are x <- [1, 2, 4] and y <- [4,5].
> [(x, y) | x <- [1, 2, 4], y <- [4,5]]
[(1,4),(1,5),(2,4),(2,5),(4,4),(4,5)]
> [(x-y, x+y) | x <- [1, 2, 4], y <- [4,5]]
[(-3,5),(-4,6),(-2,6),(-3,7),(0,8),(-1,9)]
> [(x/y, x*y) | x <- [1, 2, 4], y <- [4,5]]
[(0.25,4.0),(0.2,5.0),(0.5,8.0),(0.4,10.0),(1.0,16.0),(0.8,20.0)]
> let f x y = sqrt(x^2 + y^2)
> [ f x y | x <- [1, 2, 4], y <- [4,5]]
[4.123105625617661,5.0990195135927845,4.47213595499958,5.385164807134504,5.656854249492381,6.4031242374328485]
Guards or filter is a boolean expression that removes elements that would otherwise have been included in the list comprehension. They restricts the values produced by earlier generators.
Even number sequence
> [x | x <- [1..10], even x]
[2,4,6,8,10]
> [x | x <- [1,5,12,3,23,11,7,2], x>10]
[12,23,11]
> [(x,y) | x <- [1,3,5], y <- [2,4,6], x<y]
[(1,2),(1,4),(1,6),(3,4),(3,6),(5,6)]
Odd Number sequence
> [x | x <- [1..10], odd x]
[1,3,5,7,9]
Number factors and Prime Numbers
> let factors n = [ x | x <- [1..n], mod n x == 0]
>
> factors 15
[1,3,5,15]
>
> factors 10
[1,2,5,10]
>
> factors 100
[1,2,4,5,10,20,25,50,100]
>
> factors 17
[1,17]
> factors 19
[1,19]
> let prime n = factors n == [1, n]
>
> prime 17
True
> prime 19
True
> prime 20
False
>
{- Get all prime numbers until number n -}
> let primes_n n = [ x | x <- [1..n], prime x]
>
> primes_n 10
[2,3,5,7]
> primes_n 100
[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]
>
λ > [1..20]
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
λ > ['a'..'z']
"abcdefghijklmnopqrstuvwxyz"
λ > ['K'..'Z']
"KLMNOPQRSTUVWXYZ"
λ > [2,4..20]
[2,4,6,8,10,12,14,16,18,20]
λ > [3,6..20]
[3,6,9,12,15,18]
data MyDataType = Foo | Bar | Baz deriving (Enum, Show)
λ > succ Foo
λ > pred Baz
Which right triangle that has integers for all sides and all sides equal to or smaller than 10 has a perimeter of 24? First, let's try generating all triangles with sides equal to or smaller than 10:
. . . hint
λ > let triangles = [ (a,b,c) | c <- [1..10], b <- [1..10], a <- [1..10] ]
BELOW HERE ARE NOTES AND THINGS I HAVENT QUITE FINISHED YET
Precedence | Left associative | Non-associative | Right associative |
---|---|---|---|
9 | !! | . | |
8 | ^,^^, ** | ||
7 | *, /, div , mod , |
||
rem , quot
|
|||
6 | +, - | ||
5 | :, ++ | ||
4 | ==, /=, <, <=, >, | ||
>=,elem , notElem
|
|||
3 | && | ||
2 | || | ||
1 | >>, >>= | ||
0 |
seq
|
No definition, infixl 9 assumed.
(^^!) :: (Num a, Integral b) => a -> b -> a
a ^^! b = a ^ b
(^^^) :: (Num a, Integral b) => a -> b -> a
a ^^^ b = a ^ b
infixl 9 ^^!
infixr 9 ^^^
data Test = Test String deriving (Eq, Show)
(>:) :: Test -> Test -> Test
(Test a) >: (Test b) = Test $ "(" ++ a ++ " >: " ++ b ++ ")"
infixr 6 >:
(<:) :: Test -> Test -> Test
(Test a) <: (Test b) = Test $ "(" ++ a ++ " <: " ++ b ++ ")"
infixl 6 <:
(?:) :: Test -> Test -> Test
(Test a) ?: (Test b) = Test $ "(" ++ a ++ " ?: " ++ b ++ ")"
infix 6 ?:
main = do
print $ show $ 4 ^^! 3 ^^! 2
print $ show $ 4 ^^^ 3 ^^^ 2
print $ (Test "1") >: (Test "2") >: (Test "4")
print $ (Test "1") <: (Test "2") <: (Test "4")
print $ (Test "1") ?: ((Test "2") ?: (Test "4"))
The recursion for foldr f x ys where ys = [y1,y2,...,yk] looks like
f y1 (f y2 (... (f yk x) ...))
whereas the recursion for foldl f x ys looks like
f (... (f (f x y1) y2) ...) yk
Lowercase Type uppercase
different namespaces
Mild hungarian, xs is list of xs, two ss, list of lists.
White space is significant: Same columns
Usually f(a,b) + c d
would mean: f with a and b params, c space d mult
Haskell:
f a b + c * d
Function application binds stronger than others.
f a + b is f(a) + b
Math | Haskell |
---|---|
f(x) | f x |
f(x,y) | f x y |
f(g(x)) | f (g x) |
f(x,g(y)) | f x (g y) |
f(x)g(y) | f x * g y |
. . . Lighter syntax
thing :: type
Lists: Polymorphic
[False, True, False] :: [Bool] ['a','b','c'] :: [Char] [['a'],['a','b']] :: [[Char]]
Tuples:
(Flase, True) :: (Bool, Bool) (False, 'a', True) :: (Bool, Char, Bool) (False, ('a',False)) :: (Bool, (Char, Bool))
Mapping of one type to another:
not :: Bool -> Bool isDigit :: Char -> Bool
Arrow is right associative. Application is left associative. All functions have one param. Any with more actually return functions.
mult :: Int -> Int -> Int -> Int
// Is actually
mult :: Int -> (Int -> (Int -> Int))
mult 3 2 5
// Is actually
(((mult 3) 2) 5)
is actually
- return a function that multiplies by 3 and 2 other values
- return a function that multiplies by 3, 2 and one other value
- multiply 3, 2, and 5
Partial application.
try it
2 ^ 3 * 4 2 * 3 + 4 * 5 2 + 3 * 4 ^ 5
(2 ^ 3) * 4 (2 * 3) + (4 * 5) 2 + (3 * (4 ^ 5))
N = a 'div' length xs where a = 10 xs = [1,2,3,4]
n = a div
length xs
where a = 10
xs = [1,2,3,4]
last xs = head ( drop (lengt xs - 1) xs) last xs = xs !! (length xs - 1)