▸ Not the same as Types in, say, Java ▸ Slight Hyperbole - “If it compiles it works” ▸ Reality - “Refactor without fear” ▸ Let the computer help you help yourself 11
a 2 = Empty 3 | Cons a (List a) 4 5 cdr :: List a -> List a 6 cdr Empty = ?? 7 cdr (Cons _ rest) = rest 8 9 car :: List a -> a 10 car Empty = ?? 11 car (Cons a _) = a 12 19
= Empty 3 | Cons a (List a) 4 5 cdr :: List a -> List a 6 cdr Empty = Empty 7 cdr (Cons _ rest) = rest 8 9 car :: List a -> Maybe a 10 car Empty = Nothing 11 car (Cons a _) = Just a 12 13 data Maybe a = Nothing | Just a 14 20
Empty 3 | Cons a (List a) 4 5 concat :: List a -> List a -> List a 6 concat Empty b = b 7 concat a Empty = a 8 concat (Cons x xs) b@(Cons _ _) 9 = Cons x (concat xs b) 10 21
data, next = None ): 3 self.data = data 4 self.next = next 5 6 def concat(A, B): 7 current = A 8 while current.next != None: 9 current = current.next 10 current.next = B 11 return A 22
current.next != None: current = current.next current.next = B return A 23 concat Empty b = b concat a Empty = a concat (Cons x xs) b = Cons x (concat xs b) HASKELL FIGHT!
current.next != None: current = current.next current.next = B return A 24 concat Empty b = b concat a Empty = a concat (Cons x xs) b = Cons x (concat xs b) HASKELL TEST assertEq(concat('','bar'), 'bar') assertEq(concat('foo',''), 'foo') assertEq(concat(‘foo’,'bar'), 'foobar')
current.next != None: current = current.next current.next = B return A 25 concat Empty b = b concat a Empty = a concat (Cons x xs) b = Cons x (concat xs b) HASKELL
WAY IS TO MAKE IT SO COMPLICATED THAT THERE ARE NO OBVIOUS DEFICIENCIES, AND THE OTHER WAY IS TO MAKE IT SO SIMPLE THAT THERE ARE OBVIOUSLY NO DEFICIENCIES. - C.A.R. Hoare, 1980 ACM Turing Award Lecture HASKELL 101 26
-> b -> d) -> (x -> b) -> a -> x -> d 2 compose2 f m a x = f a (m x) 3 foldMap f m a (x:xs) = foldMap f m (f a (m x)) xs 4 = foldMap f m (compose2 f m a x) xs foldMap f m a (x:xs) = fold (compose2 f m) a x xs 47
(foldMap) which was actually not needed ▸ Our existing machinery (fold) turned out to be powerful enough to support our logic ▸ We reduced code complexity by introducing another “orthogonal” and “generic” shared vocabulary (compose2) 50
= runHandlerM $ do Just token <- reqHeader “Authorisation” auth <- liftIO $ post (showRoute ValidateR) token if isValid auth then status 403 >> json err else json albums 64
liftIO (R.randomRIO (1,100)) >>= go where go n = do guessStr <- el "div" [] [ text "Try to guess: " , inputEnter [] ] case readMaybe guessStr of Nothing -> go n Just guess -> do if | guess < n -> el_ "div" [] (text $"Go High!") <|> go n | guess > n -> el_ "div" [] (text $"Go Low!") <|> go n | otherwise -> el_ "div" [] (text $ "You guessed it!”) <|> (button [] (text "Play again")) 65 Check out https://github.com/ajnsit/concur
f (Leaf a) = Leaf (f a) 4 fmap f (Branch x y) = Branch (fmap f x) (fmap f y) 5 6 instance Foldable Tree where 7 foldl f b (Leaf a) = f b a 8 foldl f b (Branch x y) = ?? (foldl f b x) (foldl f b y) 71
-> b) -> (b -> b -> b) -> b 2 -> Tree a -> b 3 foldTree f g b (Leaf a) = f b a 4 foldTree f g b (Branch x y) 5 = g (foldTree f g b x) (foldTree f g b y) 72
a -> b) -> (b -> b -> b) -> b 2 -> Tree a -> b 3 foldTree f g b (Leaf a) = f b a 4 foldTree f g b (Branch x y) 5 = g (foldTree f g b x) (foldTree f g b y) 73
= Nothing 3 | Just a 4 5 data Either a b 6 = Left a 7 | Right b 8 9 data Person 10 = Empty 11 | Cons a (List a) 12 13 data Tree a 14 = Leaf a 15 | Branch (Tree a) (Tree a) 16 77