haskell-course

Functors

type Trace a = Int -> a
traceMap :: (a -> b) -> (Trace a) -> (Trace b)
type BinTree a = Leaf | Fork a (BinTree a) (BinTree a)
binTreeMap :: (a -> b) -> (BinTree a) -> (BinTree b)

Applicative

class Functor f => Applicative (f :: * -> *) where
  pure :: a -> f a
  (<*>) :: f (a -> b) -> f a -> f b
  GHC.Base.liftA2 :: (a -> b -> c) -> f a -> f b -> f c
  (*>) :: f a -> f b -> f b
  (<*) :: f a -> f b -> f a
  {-# MINIMAL pure, ((<*>) | liftA2) #-}
m10, m20 :: Maybe Int
m10 = pure 10
m20 = pure 20

m10 :: Maybe Int
(+) :: Int -> (Int -> Int)
(+) <$> m10 :: Maybe (Int -> Int)
(+) <$> m10 <*> m20 :: Maybe Int

IO

getLine :: IO String
putStrLn :: String -> IO ()

echo :: IO ()
echo = getLine >>= putStrLn
addHello :: String -> String
addHello name = "Hello, " + name

greet :: IO ()
greet = getLine >>= \name -> putStrLn (addHello name)

Do Notation

getLine >>=
    (\name ->  putStrLn ("Hey " ++ name ++ ", you rock!")
putStrLn "Hello, what's your name?"  >>=
  (\_ -> getLine >>=
    (\name ->  putStrLn ("Hey " ++ name ++ ", you rock!")
    )
  )
main = do  
    putStrLn "Hello, what's your name?"  
    name <- getLine  
    putStrLn ("Hey " ++ name ++ ", you rock!")  
import Data.Char

putStrLn "Hello, what's your name?"  >>=
  (\_ -> getLine >>=
    (\name ->  let bigName = map toUpper name in putStrLn ("Hey " ++ bigName ++ ", you rock!")
    )
  )
main = do  
    putStrLn "Hello, what's your name?"  
    name <- getLine
    let bigName = map toUpper name
    putStrLn ("Hey " ++ name ++ ", you rock!")  

Some useful patterns for IO

foo = getLine >> getLine

main = do
  secondLine <- foo
  putStrLn $ "The second line was: " ++ secondLine
yes = putStrLn "Yes" >> yes
yes1 = forever $ putStrLn "Yes"
isPositive = do
  n <- read <$> getLine
  if (n > 0)
    then putStrLn "positive"
    else if (n == 0) then putStrLn "zero"
      else putStrLn "negative"

A large example for IO

See https://github.com/Agnishom/PRGH17/blob/master/tut4/notes.md