Haskell Cheatsheet

1. Basic Syntax and Variables

x = 10  -- Immutable by default
name = "John"

-- Lists
numbers = [1, 2, 3, 4]

-- Tuples
tuple = ("John", 30)

-- Pattern Matching in Tuples
(x, y) = tuple

2. Functions and Higher-Order Functions

-- Simple function
greet :: String -> String
greet name = "Hello, " ++ name

-- Function application
greet "John"  -- Output: "Hello, John"

-- Higher-order functions
applyTwice :: (a -> a) -> a -> a
applyTwice f x = f (f x)

addOne :: Int -> Int
addOne x = x + 1

applyTwice addOne 5  -- Output: 7

3. Type System and Type Classes

-- Type declaration
double :: Int -> Int
double x = x * 2

-- Polymorphic function (type variable)
identity :: a -> a
identity x = x

-- Type class
class Eq a where
  (==) :: a -> a -> Bool

-- Instance of a type class
instance Eq Bool where
  True == True = True
  False == False = True
  _ == _ = False

4. Pattern Matching and Guards

-- Pattern matching in function arguments
factorial :: Int -> Int
factorial 0 = 1
factorial n = n * factorial (n - 1)

-- Guards
isAdult :: Int -> String
isAdult age
  | age >= 18 = "Adult"
  | otherwise = "Minor"

isAdult 20  -- Output: "Adult"

5. List Comprehensions

-- List comprehensions
squares = [x^2 | x <- [1..10]]

-- List comprehension with condition
evens = [x | x <- [1..20], x `mod` 2 == 0]

-- Nested list comprehension
nested = [(x, y) | x <- [1, 2, 3], y <- [4, 5]]

6. Recursion

-- Recursive function
sumList :: [Int] -> Int
sumList [] = 0
sumList (x:xs) = x + sumList xs

-- Infinite list
ones = 1 : ones

-- Fibonacci with recursion
fib :: Int -> Int
fib 0 = 0
fib 1 = 1
fib n = fib (n - 1) + fib (n - 2)

7. Monads and Functors

-- Functor example
instance Functor Maybe where
  fmap _ Nothing = Nothing
  fmap f (Just x) = Just (f x)

fmap (*2) (Just 3)  -- Output: Just 6

-- Monad example
instance Monad Maybe where
  return = Just
  Nothing >>= _ = Nothing
  Just x >>= f = f x

bindExample = Just 3 >>= (\x -> Just (x * 2))  -- Output: Just 6

8. IO and Side Effects

-- Input/output operations
main = do
  putStrLn "Enter your name:"
  name <- getLine
  putStrLn ("Hello, " ++ name)

-- Pure vs Impure
addPure :: Int -> Int -> Int
addPure x y = x + y

main = do
  putStrLn "Impure add:"
  result <- return (addPure 5 10)
  print result

9. Concurrency with Haskell

-- Forking threads
import Control.Concurrent

main = do
  forkIO (putStrLn "Thread 1")
  putStrLn "Main thread"
  threadDelay 1000000  -- Wait for a second

-- MVars (shared mutable variables)
main = do
  mvar <- newEmptyMVar
  forkIO $ do
    putStrLn "Putting 5 into MVar"
    putMVar mvar 5
  value <- takeMVar mvar
  print value  -- Output: 5

10. Laziness and Infinite Data Structures

-- Infinite list
ones = repeat 1

-- Lazy evaluation
firstThree = take 3 ones  -- Output: [1, 1, 1]

-- Custom infinite list
evens = [2, 4..]

firstFiveEvens = take 5 evens  -- Output: [2, 4, 6, 8, 10]

11. Algebraic Data Types

-- Simple algebraic data type
data Shape = Circle Float | Rectangle Float Float

-- Pattern matching on ADTs
area :: Shape -> Float
area (Circle r) = pi * r^2
area (Rectangle w h) = w * h

-- Using ADTs
main = do
  let c = Circle 5.0
  let r = Rectangle 10.0 5.0
  print (area c)  -- Output: 78.53982
  print (area r)  -- Output: 50.0

12. Higher-Order Functions and Currying

-- Function composition
addOne = (+1)
multiplyByTwo = (*2)
combined = addOne . multiplyByTwo
combined 3  -- Output: 7

-- Currying example
add :: Int -> Int -> Int
add x y = x + y

addThree = add 3
addThree 5  -- Output: 8

13. Error Handling with Maybe and Either

-- Maybe type for error handling
safeDiv :: Int -> Int -> Maybe Int
safeDiv _ 0 = Nothing
safeDiv x y = Just (x `div` y)

result = safeDiv 10 0  -- Output: Nothing

-- Either type
safeSqrt :: Float -> Either String Float
safeSqrt x
  | x < 0 = Left "Cannot compute square root of negative number"
  | otherwise = Right (sqrt x)

result = safeSqrt (-1)  -- Output: Left "Cannot compute square root of negative number"

14. Type Synonyms and Newtypes

-- Type synonyms
type StringAlias = String

-- Newtype (more efficient than data)
newtype Name = Name String deriving Show

getName :: Name -> String
getName (Name name) = name

15. Custom Type Classes

-- Define a type class
class Showable a where
  show' :: a -> String

-- Implement the type class
instance Showable Bool where
  show' True = "True"
  show' False = "False"

instance Showable Int where
  show' x = show x

showExample = show' True  -- Output: "True"

16. Foldable and Map Operations

-- Foldable (foldr, foldl)
sumList :: [Int] -> Int
sumList = foldr (+) 0

-- Map operations
squaredList = map (^2) [1, 2, 3, 4]
filtered = filter even squaredList  -- Output: [4, 16]

17. Monads and Functors

-- Functor: Map functions over wrapped values
class Functor f where
  fmap :: (a -> b) -> f a -> f b

instance Functor [] where
  fmap = map

-- Example usage of Functor
fmap (*2) [1, 2, 3]  -- Output: [2, 4, 6]

-- Monad: Handle wrapped computations
class Monad m where
  (>>=) :: m a -> (a -> m b) -> m b
  return :: a -> m a

instance Monad Maybe where
  return = Just
  Nothing >>= _ = Nothing
  Just x >>= f = f x

-- Example usage of Monad
Just 5 >>= (\x -> Just (x + 1))  -- Output: Just 6

18. Concurrency

-- Concurrency in Haskell using threads and shared variables
import Control.Concurrent

-- Create and manage threads
main = do
  forkIO (putStrLn "Thread 1")
  putStrLn "Main thread"
  threadDelay 1000000  -- Delay for 1 second

-- MVars (shared mutable variables)
main = do
  mvar <- newEmptyMVar
  forkIO $ do
    putStrLn "Putting value into MVar"
    putMVar mvar 10
  value <- takeMVar mvar
  print value  -- Output: 10

19. Type Classes

-- Defining and using custom type classes
class Showable a where
  show' :: a -> String

-- Implementing the Showable type class for Bool
instance Showable Bool where
  show' True = "True"
  show' False = "False"

-- Implementing the Showable type class for Int
instance Showable Int where
  show' x = show x

-- Example usage of type classes
show' True  -- Output: "True"
show' 42    -- Output: "42"