InterviewPitch
Haskell interview questions

Haskell Interview Questions with Answers

Most Asked Haskell Interview Questions for Software Engineer Roles

100+ QuestionsDetailed AnswersCode ExamplesUpdated for 2026

Haskell Interview Questions & Answers

This page provides a comprehensive collection of Haskell interview questions and answers, curated for software engineers, functional programming enthusiasts, backend developers, and candidates preparing for technical interviews that emphasise pure functional programming, strong static typing, and modern software design. Haskell is a **purely functional, statically typed programming language** renowned for its expressive type system, lazy evaluation, and elegant handling of side effects through monads. It is widely used in finance, blockchain, compiler construction, and data‑intensive applications where correctness, maintainability, and concurrency are paramount. Haskell’s emphasis on immutability and referential transparency leads to more predictable and testable code, making it a favourite for high‑assurance systems. This guide covers beginner, intermediate, and advanced Haskell topics – from basic syntax, algebraic data types, and pattern matching to monads, type families, GADTs, and real‑world performance considerations. Whether you're new to functional programming or a seasoned Haskeller, these questions will help you master the language and ace your next interview.

Why Learn Haskell?

  • Purely functional paradigm – write side‑effect‑free, composable, and referentially transparent code
  • Strong static type system with type inference – catch errors at compile time and enforce program correctness
  • Lazy evaluation – enables infinite data structures, modularity, and efficient resource usage
  • Concurrency and parallelism – lightweight threads, software transactional memory (STM), and async I/O
  • Rich ecosystem – libraries for web development (Servant, Yesod), data science, finance, and more
  • Used in industry – companies like Standard Chartered, Barclays, Facebook, and GitHub rely on Haskell
  • Excellent for DSLs – elegant syntax and powerful type‑level programming for custom domain languages

Top 100 Haskell Interview Questions

Beginner
1. What is Haskell and what are its key features?

Haskell is a purely functional, statically typed programming language with lazy evaluation and strong type inference.

  • Purely Functional: Functions have no side effects
  • Lazy Evaluation: Expressions evaluated only when needed
  • Strong Static Typing: Type safety with type inference
  • Immutable Data: Data cannot be modified after creation
  • Pattern Matching: Elegant data destructuring
haskell
// Haskell Q1: What is Haskell and what are its key features?
"Haskell is a purely functional, statically typed programming language 
with lazy evaluation and strong type inference. Key features include:

1. Purely Functional: Functions have no side effects
2. Lazy Evaluation: Expressions evaluated only when needed
3. Strong Static Typing: Type safety with type inference
4. Immutable Data: Data cannot be modified after creation
5. Pattern Matching: Elegant data destructuring
6. Type Classes: Ad-hoc polymorphism
7. Monads: Handling side effects and composition
8. Higher-Order Functions: Functions as first-class citizens
9. Algebraic Data Types: Sum and product types
10. GHC: Glasgow Haskell Compiler"
Beginner
2. What is the difference between let and where in Haskell?

Both 'let' and 'where' define local bindings, but differ in placement and scope.

  • let: Appears before the expression, narrower scope
  • where: Appears after the expression, can span multiple guards
  • Readability: 'where' often more readable for pattern matching
  • Composition: 'let' can be used anywhere expressions are allowed
haskell
// Haskell Q2: What is the difference between let and where in Haskell?
"Both 'let' and 'where' define local bindings, but differ in placement:

'let' is an expression:
let x = 5
    y = 10
in x + y

'where' is a clause:
calculate x = result
  where result = x * 2

Key Differences:
1. Placement: 'let' appears before the expression, 'where' after
2. Scope: 'let' has narrower scope, 'where' can span multiple guards
3. Readability: 'where' often more readable for pattern matching
4. Composition: 'let' can be used anywhere expressions are allowed

Examples:
-- let binding
add x y = let sum = x + y in sum * 2

-- where binding
add x y = result * 2
  where result = x + y

-- Pattern matching with where
max x y | x > y     = x
        | otherwise = y
  where diff = abs (x - y)"
Beginner
3. What are algebraic data types?

Algebraic Data Types (ADTs) combine product and sum types to create complex data structures.

  • Product Types: Combine multiple values (AND)
  • Sum Types: Choose between alternatives (OR)
  • Pattern Matching: Deconstruct ADTs
  • Type Safety: Compile-time guarantees
haskell
// Haskell Q3: What are algebraic data types?
"Algebraic Data Types (ADTs) combine product and sum types:

1. Product Types (AND): Combine multiple values
data Person = Person String Int  -- Name and Age

2. Sum Types (OR): Choose between alternatives
data Bool = True | False

3. Both together:
data Shape = Circle Float | Rectangle Float Float

Key Features:
- Pattern matching for deconstruction
- Type safety at compile time
- Represent domain models clearly

Examples:
data Maybe a = Nothing | Just a
data Either a b = Left a | Right b
data Tree a = Empty | Node a (Tree a) (Tree a)

-- Using pattern matching
describeShape (Circle r) = "Circle with radius " ++ show r
describeShape (Rectangle w h) = "Rectangle " ++ show w ++ "x" ++ show h"
Intermediate
4. What is a Monad?

Monads are a design pattern for handling side effects and sequencing computations in a pure functional way.

  • Maybe: Handle possible failure
  • List: Handle multiple values
  • IO: Handle input/output
  • State: Handle stateful computations
haskell
// Haskell Q4: What is a Monad?
"A Monad is a design pattern for handling side effects and sequencing:

Monad Laws:
1. Left identity: return a >>= f = f a
2. Right identity: m >>= return = m
3. Associativity: (m >>= f) >>= g = m >>= (\x -> f x >>= g)

Key Monads in Haskell:
1. Maybe: Handle possible failure
2. List: Handle multiple values
3. IO: Handle input/output
4. State: Handle stateful computations
5. Either: Handle exceptions
6. Reader: Handle configuration
7. Writer: Handle logging
8. Cont: Handle continuations

Basic Monad Operations:
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b

Example:
-- Maybe Monad
safeDiv :: Int -> Int -> Maybe Int
safeDiv _ 0 = Nothing
safeDiv x y = Just (x `div` y)

-- Using do notation
calculate :: Int -> Int -> Maybe Int
calculate x y = do
  z <- safeDiv x y
  w <- safeDiv z 2
  return w"
Intermediate
5. What is lazy evaluation?

Lazy evaluation means expressions are evaluated only when needed, enabling infinite data structures and improved modularity.

  • Thunks: Delayed computations
  • Memoization: Results cached after first evaluation
  • Infinite Data: Can work with infinite lists
  • Efficiency: Avoids unnecessary computations
haskell
// Haskell Q5: What is lazy evaluation?
"Lazy evaluation means expressions are evaluated only when needed:

Key Concepts:
1. Thunks: Delayed computations
2. Memoization: Results cached after first evaluation
3. Infinite Data: Can work with infinite lists
4. Efficiency: Avoids unnecessary computations

Benefits:
1. Performance: Only compute what's needed
2. Modularity: Separate generation from consumption
3. Infinite structures: Work with infinite data

Example:
-- Infinite list of numbers
ones = 1 : ones
-- Take first 5 elements (only evaluates what's needed)
take 5 ones  -- [1,1,1,1,1]

-- Fibonacci sequence (infinite)
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
take 10 fibs  -- [0,1,1,2,3,5,8,13,21,34]

-- Only evaluates until condition met
firstEven = head (filter even [1..])

Drawbacks:
1. Space leaks: When thunks accumulate
2. Performance unpredictability
3. Debugging difficulty"
Beginner
6. What are type classes?

Type classes provide ad-hoc polymorphism in Haskell, similar to interfaces in OOP languages.

  • Eq: Equality operations
  • Ord: Ordering operations
  • Show: String conversion
  • Read: Parsing from strings
  • Num: Numeric operations
  • Functor: Mapping operations
  • Applicative: Sequential application
  • Monad: Sequencing operations
haskell
// Haskell Q6: What are type classes?
"Type classes provide ad-hoc polymorphism:

Key Type Classes:
1. Eq: Equality (==)
2. Ord: Ordering (compare)
3. Show: String conversion (show)
4. Read: Parsing (read)
5. Num: Numeric operations
6. Functor: Map (fmap)
7. Applicative: Sequential application
8. Monad: Sequencing

Examples:
-- Defining a type class
class Printable a where
  print :: a -> String

-- Instantiating a type class
instance Printable Int where
  print n = "Int: " ++ show n

instance Printable Bool where
  print True = "True"
  print False = "False"

-- Using type class constraints
showPrintable :: Printable a => a -> String
showPrintable x = "Value: " ++ print x

-- Deriving type classes
data Person = Person String Int
  deriving (Eq, Show, Ord)"
Beginner
7. What is pattern matching?

Pattern matching deconstructs data structures and binds variables to values.

  • Literal Patterns: Match specific values
  • Variable Patterns: Bind to any value
  • Wildcard Patterns: Match anything (ignored)
  • Constructor Patterns: Match data constructors
  • List Patterns: Match list structures
  • Tuple Patterns: Match tuple structures
  • As-patterns: Bind entire pattern
haskell
// Haskell Q7: What is pattern matching?
"Pattern matching deconstructs data structures:

Basic Patterns:
1. Literal: matches specific values
2. Variable: matches any value
3. Wildcard: matches any (ignored)
4. Constructor: matches data constructors
5. List: matches list patterns
6. Tuple: matches tuple patterns
7. As-pattern: binds entire pattern

Examples:
-- Literal pattern
isZero 0 = True
isZero _ = False

-- Constructor pattern
data Maybe a = Nothing | Just a
extractValue (Just x) = x
extractValue Nothing = error "Nothing"

-- List pattern
sumList [] = 0
sumList (x:xs) = x + sumList xs

-- Tuple pattern
addPair (x, y) = x + y

-- As-pattern
duplicateList lst@(x:xs) = lst ++ xs

-- Multiple patterns
describe x = case x of
  0 -> "Zero"
  1 -> "One"
  _ -> "Other"
Intermediate
8. What is the difference between foldl and foldr?

foldl and foldr differ in evaluation order and associativity.

  • foldl: Left fold, strict evaluation, can overflow stack
  • foldr: Right fold, lazy evaluation, works with infinite lists
  • foldl': Strict version of foldl (recommended)
  • Performance: foldl' for numeric operations, foldr for construction
haskell
// Haskell Q8: What is the difference between foldl and foldr?
"foldl and foldr differ in evaluation order and associativity:

foldl (left fold):
foldl :: (b -> a -> b) -> b -> [a] -> b
- Associates to the left
- Strict evaluation
- Can cause stack overflow on large lists

foldr (right fold):
foldr :: (a -> b -> b) -> b -> [a] -> b
- Associates to the right
- Lazy evaluation
- Works with infinite lists

Examples:
-- foldl
foldl (+) 0 [1,2,3]  -- (((0+1)+2)+3)

-- foldr
foldr (+) 0 [1,2,3]  -- (1+(2+(3+0)))

-- Difference for large lists
-- foldl' is strict version of foldl (recommended)
foldl' (+) 0 [1..1000000]  -- Efficient

-- Using foldr with infinite lists
take 5 (foldr (:) [] [1..])  -- [1,2,3,4,5] (works)
take 5 (foldl (flip (:)) [] [1..])  -- Doesn't terminate"
Intermediate
9. What are higher-order functions?

Higher-order functions take functions as arguments or return functions.

  • map: Apply function to each element
  • filter: Select elements based on predicate
  • foldl/foldr: Reduce list to single value
  • composition: Function composition (.)
  • application: Function application ($)
haskell
// Haskell Q9: What are higher-order functions?
"Higher-order functions take functions as arguments or return functions:

Common Higher-Order Functions:
1. map: Apply function to each element
2. filter: Select elements based on predicate
3. foldl/foldr: Reduce list to single value
4. (.) : Function composition
5. ($) : Function application
6. flip: Reverse function arguments
7. const: Constant function
8. id: Identity function

Examples:
-- map
map (*2) [1,2,3,4]  -- [2,4,6,8]

-- filter
filter even [1..10]  -- [2,4,6,8,10]

-- Function composition
compose = (.) :: (b -> c) -> (a -> b) -> a -> c
result = (sum . map (*2) . filter even) [1..10]

-- Creating functions
add = (+)
add5 = add 5
add5 10  -- 15

-- Returning functions
makeAdder :: Int -> (Int -> Int)
makeAdder x = \y -> x + y

add10 = makeAdder 10
add10 5  -- 15"
Intermediate
10. What is the State Monad?

State Monad handles stateful computations in a pure functional way.

  • get: Get current state
  • put: Set new state
  • modify: Update state
  • state: Create State computation
haskell
// Haskell Q10: What is the State Monad?
"The State Monad handles stateful computations in a pure functional way:

State Monad Definition:
newtype State s a = State { runState :: s -> (a, s) }

Key Functions:
1. get: Get current state
2. put: Set new state
3. modify: Update state
4. state: Create State computation

Examples:
-- Counter with State Monad
import Control.Monad.State

increment :: State Int Int
increment = do
  count <- get
  put (count + 1)
  return count

-- Using State
runState increment 0  -- (0,1)

-- Complex state
data AppState = AppState { counter :: Int, values :: [Int] }

updateState :: State AppState ()
updateState = do
  modify (\s -> s { counter = counter s + 1 })
  modify (\s -> s { values = counter s : values s })

-- More practical example
fibonacci :: Int -> State Int Int
fibonacci 0 = return 0
fibonacci n = do
  prev <- fibonacci (n-1)
  current <- get
  put (prev + current)
  return current"
Intermediate
11. What is the Reader Monad?

Reader Monad provides a way to pass configuration or environment through computations.

  • reader: Create Reader computation
  • ask: Get the environment
  • local: Modify environment
  • Uses: Configuration management, dependency injection
haskell
// Haskell Q11: What is the Reader Monad?
"The Reader Monad provides a way to pass configuration or environment:

Reader Definition:
newtype Reader r a = Reader { runReader :: r -> a }

Key Functions:
1. reader: Create Reader computation
2. ask: Get the environment
3. local: Modify environment

Examples:
import Control.Monad.Reader

-- Configuration
data Config = Config { verbose :: Bool, logLevel :: Int }

-- Computation with config
logMessage :: String -> Reader Config ()
logMessage msg = do
  config <- ask
  if verbose config
    then liftIO (putStrLn ("[LOG] " ++ msg))
    else return ()

-- Environment function
calculate :: Reader Config Int
calculate = do
  config <- ask
  return (logLevel config * 2)

-- Using Reader
runReader calculate (Config True 3)  -- 6

-- Composing Reader
withVerbose :: Reader Config a -> Reader Config a
withVerbose action = local (\c -> c { verbose = True }) action"
Intermediate
12. What is the Writer Monad?

Writer Monad collects output or logging alongside computation.

  • writer: Create Writer computation
  • tell: Add output
  • listen: Listen to output
  • pass: Modify output
  • Uses: Logging, tracing, accumulating results
haskell
// Haskell Q12: What is the Writer Monad?
"The Writer Monad collects output or logging alongside computation:

Writer Definition:
newtype Writer w a = Writer { runWriter :: (a, w) }

Key Functions:
1. writer: Create Writer computation
2. tell: Add output
3. listen: Listen to output
4. pass: Modify output

Examples:
import Control.Monad.Writer

-- Logging with Writer
calculateSum :: [Int] -> Writer [String] Int
calculateSum [] = return 0
calculateSum (x:xs) = do
  tell ["Adding " ++ show x]
  rest <- calculateSum xs
  return (x + rest)

-- Using Writer
let (result, log) = runWriter (calculateSum [1,2,3,4])
-- result = 10
-- log = ["Adding 1","Adding 2","Adding 3","Adding 4"]

-- Multiple writers
analysis :: Int -> Writer (String, [Int]) Int
analysis n = do
  tell ("Processing: " ++ show n, [n])
  return (n * 2)

-- Combining logs
process :: Int -> Writer [String] Int
process n = do
  tell ["Step 1"]
  let x = n * 2
  tell ["Step 2: " ++ show x]
  return x"
Intermediate
13. What is the Maybe Monad?

Maybe Monad handles computations that might fail.

  • Nothing: Represents failure
  • Just: Represents success with value
  • maybe: Pattern match on Maybe
  • fromMaybe: Extract value with default
  • Uses: Error handling, optional values
haskell
// Haskell Q13: What is the Maybe Monad?
"The Maybe Monad handles computations that might fail:

Maybe Definition:
data Maybe a = Nothing | Just a

Key Functions:
1. maybe: Pattern match on Maybe
2. fromMaybe: Extract value with default
3. isJust/isNothing: Check status
4. catMaybes: Filter out Nothings
5. mapMaybe: Map and filter

Examples:
-- Safe division
safeDiv :: Int -> Int -> Maybe Int
safeDiv _ 0 = Nothing
safeDiv x y = Just (x `div` y)

-- Chaining computations
calculate :: Int -> Int -> Maybe Int
calculate x y = do
  a <- safeDiv x y
  b <- safeDiv a 2
  return b

-- Using maybe
maybeResult = maybe 0 id (Just 5)  -- 5

-- Error handling with do notation
processValue :: Maybe Int -> Maybe Int -> Maybe Int
processValue mx my = do
  x <- mx
  y <- my
  return (x + y)

-- Alternative to failure
safeHead :: [a] -> Maybe a
safeHead [] = Nothing
safeHead (x:_) = Just x

-- Using Maybe in practice
fetchUser :: Int -> Maybe String
fetchUser 1 = Just "Alice"
fetchUser 2 = Just "Bob"
fetchUser _ = Nothing"
Intermediate
14. What is the Either Monad?

Either Monad handles computations that can fail with an error message.

  • Left: Represents error
  • Right: Represents success
  • either: Pattern match on Either
  • Uses: Error handling with messages
haskell
// Haskell Q14: What is the Either Monad?
"The Either Monad handles computations that can fail with an error:

Either Definition:
data Either a b = Left a | Right b

Key Functions:
1. either: Pattern match on Either
2. isLeft/isRight: Check status
3. fromLeft/fromRight: Extract values
4. lefts/rights: Filter lists

Examples:
-- Error handling with Either
safeDiv :: Int -> Int -> Either String Int
safeDiv _ 0 = Left "Division by zero"
safeDiv x y = Right (x `div` y)

-- Chaining with do notation
calculate :: Int -> Int -> Either String Int
calculate x y = do
  a <- safeDiv x y
  b <- safeDiv a 2
  return b

-- Using Either
processValue :: Either String Int -> Either String Int
processValue (Left err) = Left ("Error: " ++ err)
processValue (Right val) = Right (val * 2)

-- Validation
validateAge :: Int -> Either String Int
validateAge age
  | age < 0 = Left "Negative age"
  | age > 150 = Left "Too old"
  | otherwise = Right age

-- Using either
handleResult = either (error . show) (*2) (Right 5)

-- Monad transformer for Either
type MyMonad = EitherT String IO"
Intermediate
15. What are applicative functors?

Applicative functors allow sequential application of functions in a context.

  • pure: Lift value into applicative
  • <*>: Apply function in context
  • <$>: Functor map
  • Uses: Validation, parsing, sequencing
haskell
// Haskell Q15: What are applicative functors?
"Applicative functors allow sequential application of functions:

Applicative Definition:
class Functor f => Applicative f where
  pure :: a -> f a
  (<*>) :: f (a -> b) -> f a -> f b

Key Functions:
1. pure: Lift value into applicative
2. <*>: Apply function in context
3. <$>: Functor map (same as fmap)
4. <$>: Alias for fmap
5. *>: Sequence ignoring left result
6. <*: Sequence ignoring right result

Examples:
-- Using Applicative with Maybe
justAdd = Just (+)
justAdd <*> Just 3 <*> Just 5  -- Just 8

-- Using Applicative with lists
(*) <$> [1,2,3] <*> [4,5,6]  -- [4,5,6,8,10,12,...]

-- Validation with Applicative
data Person = Person { name :: String, age :: Int }

validateName :: String -> Maybe String
validateName name
  | null name = Nothing
  | otherwise = Just name

validateAge :: Int -> Maybe Int
validateAge age
  | age < 0 || age > 150 = Nothing
  | otherwise = Just age

createPerson :: String -> Int -> Maybe Person
createPerson name age = Person <$> validateName name <*> validateAge age

-- Applicative laws
-- Identity: pure id <*> v = v
-- Composition: pure (.) <*> u <*> v <*> w = u <*> (v <*> w)
-- Homomorphism: pure f <*> pure x = pure (f x)
-- Interchange: u <*> pure y = pure ($ y) <*> u"
Intermediate
16. What are functors?

Functors represent containers or computations that can be mapped over.

  • fmap: Apply function to inner value
  • <$>: Infix version of fmap
  • Laws: Identity and composition
  • Uses: Mapping over data structures
haskell
// Haskell Q16: What are functors?
"Functors represent containers or computations that can be mapped:

Functor Definition:
class Functor f where
  fmap :: (a -> b) -> f a -> f b

Key Functions:
1. fmap: Apply function to inner value
2. (<$>): Infix version of fmap
3. ($>): Replace inner value
4. (<&>): Flipped version of fmap

Functor Laws:
1. Identity: fmap id = id
2. Composition: fmap (f . g) = fmap f . fmap g

Examples:
-- Functor instances
fmap (*2) [1,2,3]  -- [2,4,6]
fmap (+1) (Just 5)  -- Just 6
fmap show (Right 10)  -- Right "10"

-- Using <$>
(*2) <$> [1,2,3]  -- [2,4,6]

-- Functor composition
data MaybeList a = MaybeList (Maybe [a])

instance Functor MaybeList where
  fmap f (MaybeList Nothing) = MaybeList Nothing
  fmap f (MaybeList (Just xs)) = MaybeList (Just (map f xs))

-- Using functors in practice
doubleMaybe = fmap (*2) . Just  -- Just 2
doubleMaybeList = fmap (fmap (*2))  -- Double values in nested structure

-- Deriving Functor
data Tree a = Leaf a | Branch (Tree a) (Tree a)
  deriving (Functor, Show)"
Advanced
17. What are monad transformers?

Monad transformers combine multiple monads into one.

  • MaybeT: Adds Maybe behavior
  • EitherT: Adds Either behavior
  • ReaderT: Adds Reader behavior
  • WriterT: Adds Writer behavior
  • StateT: Adds State behavior
  • lift: Lift computation to transformer
haskell
// Haskell Q17: What are monad transformers?
"Monad transformers combine multiple monads into one:

Common Transformers:
1. MaybeT: Adds Maybe behavior
2. EitherT: Adds Either behavior
3. ReaderT: Adds Reader behavior
4. WriterT: Adds Writer behavior
5. StateT: Adds State behavior
6. ExceptT: Adds Exception handling

Key Functions:
1. lift: Lift computation to transformer
2. liftIO: Lift IO computation
3. runXxxT: Run the transformer

Examples:
import Control.Monad.Trans.Maybe
import Control.Monad.Trans.Reader

type AppM = ReaderT Config (MaybeT IO)

data Config = Config { env :: String }

runApp :: AppM a -> Config -> IO (Maybe a)
runApp app config = runMaybeT (runReaderT app config)

-- Using transformer
getConfig :: AppM String
getConfig = do
  config <- ask
  return (env config)

-- Lifting operations
logMessage :: String -> AppM ()
logMessage msg = liftIO (putStrLn msg)

-- Combining transformers
data AppState = AppState { counter :: Int }
type MyApp = StateT AppState (ReaderT Config (MaybeT IO))

-- Using multiple transformers
incrementCounter :: MyApp ()
incrementCounter = do
  modify (\s -> s { counter = counter s + 1 })
  count <- gets counter
  liftIO (putStrLn ("Counter: " ++ show count))"
Intermediate
18. What is the difference between IO and pure functions?

IO functions have side effects, while pure functions don't.

  • Pure: No side effects, referentially transparent
  • IO: Can perform I/O, not referentially transparent
  • Separation: Keep IO separate from pure logic
  • Testing: Pure functions are easier to test
haskell
// Haskell Q18: What is the difference between IO and pure functions?
"IO functions have side effects, pure functions don't:

Pure Functions:
- No side effects
- Same input = same output
- Referentially transparent
- Can be reasoned about mathematically
- Easy to test

IO Functions:
- Can have side effects
- Can perform input/output
- Can read/write files
- Can interact with the world
- Not referentially transparent

Examples:
-- Pure function
add :: Int -> Int -> Int
add x y = x + y  -- Always same result

-- IO function
getLine :: IO String  -- Reads from stdin
putStrLn :: String -> IO ()  -- Writes to stdout

-- Combining pure and IO
readFileAndProcess :: FilePath -> IO Int
readFileAndProcess path = do
  content <- readFile path
  return (length content)  -- Pure processing

-- Lifting pure functions into IO
main = do
  content <- readFile "file.txt"
  let result = pureFunction content  -- Pure
  putStrLn (show result)

pureFunction :: String -> Int
pureFunction = length"
Intermediate
19. What is the difference between >>= and >>?

>>= (bind) passes the result to a function, while >> (then) sequences actions ignoring the result.

  • >>=: Used when you need the result
  • >>: Used for side effects only
  • Do notation: Syntactic sugar for both
haskell
// Haskell Q19: What is the difference between >>= and >>?
"Both are sequencing operators but with different purposes:

(>>=) (bind):
- Takes a monadic value and a function
- Passes the value to the function
- Used when you need the result

(>>) (then):
- Sequences two monadic actions
- Ignores the result of the first
- Used for side effects only

Examples:
-- Using bind
readNumber :: IO Int
readNumber = do
  line <- getLine
  return (read line)

-- Using bind with function
main = do
  x <- readNumber
  y <- readNumber
  print (x + y)

-- Using then for side effects
main = putStrLn "Start" >> putStrLn "End"

-- Equivalent using do notation
main = do
  putStrLn "Start"
  putStrLn "End"

-- Complex example
processFile :: FilePath -> IO ()
processFile path = do
  content <- readFile path
  putStrLn "File read" >> putStrLn "Processing..." >> putStrLn "Done"

-- Desugared
processFile path =
  readFile path >>= \content ->
  putStrLn "File read" >>
  putStrLn "Processing..." >>
  putStrLn "Done"
Advanced
20. What is the difference between foldl, foldl', and foldr?

Three fold variants with different evaluation strategies.

  • foldl: Lazy left fold, can overflow stack
  • foldl': Strict left fold, memory efficient
  • foldr: Lazy right fold, works with infinite lists
haskell
// Haskell Q20: What is the difference between foldl, foldl', and foldr?
"Three fold variants with different evaluation strategies:

foldl (left fold):
- Lazy left fold
- Can cause stack overflow
- Not recommended for large lists

foldl' (strict left fold):
- Strict left fold
- Memory efficient
- Recommended for large lists

foldr (right fold):
- Lazy right fold
- Can work with infinite lists
- Good for constructing data

Examples:
-- foldl (can overflow)
foldl (+) 0 [1..1000000]  -- May stack overflow

-- foldl' (safe)
import Data.List (foldl')
foldl' (+) 0 [1..1000000]  -- Safe

-- foldr with infinite list
foldr (:) [] [1..]  -- Can work with infinite

-- Performance comparison
sumList1 = foldl (+) 0  -- Slow, can overflow
sumList2 = foldl' (+) 0  -- Fast, safe
sumList3 = foldr (+) 0  -- Slow for large lists

-- Type signatures
foldl :: (b -> a -> b) -> b -> [a] -> b
foldl' :: (b -> a -> b) -> b -> [a] -> b
foldr :: (a -> b -> b) -> b -> [a] -> b

-- When to use each:
-- foldl': For numeric accumulations
-- foldr: For constructing data structures
-- foldl: Rarely (use foldl' instead)

-- foldl' vs foldr
product1 = foldl' (*) 1 [1..10]  -- 3628800
product2 = foldr (*) 1 [1..10]  -- Same result but different evaluation"
Intermediate
21. What are the benefits of lazy evaluation?

Lazy evaluation provides several benefits including infinite data structures and improved modularity.

  • Infinite Data: Can work with infinite lists
  • Efficiency: Only compute what's needed
  • Modularity: Separate generation from consumption
  • Memoization: Results cached automatically
haskell
// Haskell Q21: What are the benefits of lazy evaluation?
"Lazy evaluation provides several benefits:

Benefits:
1. Infinite Data Structures: Can work with infinite lists
2. Efficiency: Only compute what's needed
3. Modularity: Separate generation from consumption
4. Memoization: Results cached automatically
5. Composition: Easier to compose functions

Examples:
-- Infinite list
nats = [1..]
take 10 nats  -- [1,2,3,4,5,6,7,8,9,10]

-- Lazy processing
firstEven = head (filter even [1..])  -- 2

-- Memoization
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
fib n = fibs !! n  -- O(n) after first calculation

-- Modular design
generateNumbers = [1..]
processNumbers = take 20 . filter odd . map (*2)

-- Only evaluates necessary elements
evaluate = processNumbers generateNumbers

-- Space efficiency
sumSquares = sum . map (^2) . takeWhile (<100)  -- Only evaluates needed"
Advanced
22. What is the difference between monad and applicative?

Monad and Applicative differ in expressiveness and capabilities.

  • Applicative: Sequential application, no dependencies
  • Monad: Sequential composition with dependencies
  • Every Monad is Applicative, but not vice versa
haskell
// Haskell Q22: What is the difference between monad and applicative?
"Monad and Applicative differ in expressiveness:

Applicative:
- Sequential application of pure functions
- No dependency between computations
- Cannot use previous results to determine next

Monad:
- Sequential composition with dependencies
- Can use results to determine next computation
- More powerful than Applicative

Examples:
-- Applicative style
validateAndCreate :: Maybe String -> Maybe Int -> Maybe Person
validateAndCreate name age = Person <$> name <*> age

-- Monad style
processUser :: Int -> Maybe String
processUser id = do
  user <- fetchUser id
  if user == "admin"
    then Just "Admin access"
    else Just "User access"

-- Applicative can't do this:
getAndProcess :: IO Int
getAndProcess = do
  x <- getLine >>= return . read
  y <- getLine >>= return . read
  return (x + y)

-- Every Monad is Applicative, but not every Applicative is Monad
-- Monad provides: (>>=) :: m a -> (a -> m b) -> m b
-- Applicative provides: (<*>) :: f (a -> b) -> f a -> f b"
Beginner
23. What are type synonyms?

Type synonyms provide alternative names for existing types.

  • Readability: Domain-specific names
  • Documentation: Self-documenting code
  • Abstraction: Hide implementation details
haskell
// Haskell Q23: What are type synonyms?
"Type synonyms provide alternative names for existing types:

Type Synonym Syntax:
type Name = ExistingType

Benefits:
1. Improved readability
2. Domain-specific names
3. Documentation
4. Abstraction

Examples:
-- Basic type synonyms
type String = [Char]
type FilePath = String
type UserId = Int

-- More complex synonyms
type Name = String
type Age = Int
type Address = String

type Person = (Name, Age, Address)

-- Using type synonyms
getUserInfo :: UserId -> IO (String, String)
getUserInfo uid = do
  name <- getUserName uid
  email <- getUserEmail uid
  return (name, email)

-- Nested synonyms
type NameList = [String]
type NameListList = [NameList]

-- Synonyms with parameters
type AssocList k v = [(k, v)]
type MapFunc k v = k -> v

-- Practical example
data Database = Database
type Query = String
type Result = [String]

executeQuery :: Database -> Query -> IO Result"
Intermediate
24. What are newtypes?

Newtypes create new types with the same runtime representation.

  • Type Safety: Different types for different purposes
  • Zero Overhead: No runtime cost
  • Different Instances: Different type class instances
haskell
// Haskell Q24: What are newtypes?
"Newtypes create new types with the same runtime representation:

Newtype Syntax:
newtype MyType = MyType ExistingType

Benefits:
1. Type safety without overhead
2. Different instances for same representation
3. Zero-cost abstraction

Examples:
-- Creating newtypes
newtype Username = Username String
newtype Password = Password String
newtype Age = Age Int

-- Type safety
login :: Username -> Password -> Bool
login (Username u) (Password p) = u == "admin" && p == "secret"

-- Different instances
newtype Identity a = Identity a
newtype Maybe a = Just a | Nothing

-- Deriving instances
newtype Age = Age Int
  deriving (Eq, Ord, Show, Num)

-- Using newtypes for safety
newtype Meters = Meters Double
newtype Kilometers = Kilometers Double

toMeters :: Kilometers -> Meters
toMeters (Kilometers km) = Meters (km * 1000)

-- Newtype vs Type
type StringAlias = String  -- Same type
newtype StringWrapper = StringWrapper String  -- New type"
Intermediate
25. What is the difference between newtype and data?

Newtype and data have different characteristics and use cases.

  • Newtype: One constructor, one field, zero overhead
  • Data: Multiple constructors, multiple fields, runtime overhead
  • Use: Newtype for type safety, Data for ADTs
haskell
// Haskell Q25: What is the difference between newtype and data?
"Newtype and data have different characteristics:

Newtype:
- Only one constructor
- Only one field
- Zero runtime overhead
- Can only be used for new types

Data:
- Multiple constructors
- Multiple fields
- Runtime overhead
- Can define algebraic data types

Examples:
-- Newtype (one constructor, one field)
newtype Age = Age Int
newtype Name = Name String

-- Data (multiple constructors, multiple fields)
data Person = Person Name Age
data Maybe a = Nothing | Just a
data Tree a = Leaf | Node a (Tree a) (Tree a)

-- Newtype with deriving
newtype Seconds = Seconds Int
  deriving (Eq, Ord, Num, Show)

-- Data with deriving
data Color = Red | Green | Blue
  deriving (Eq, Show)

-- Performance difference
newtype NewType = NT Int  -- Compiles to Int
data DataType = DT Int  -- Compiles to wrapper structure

-- When to use newtype vs data
-- Newtype: When you want type safety and the type has one field
-- Data: When you need multiple constructors or fields"
Advanced
26. What are GADTs?

Generalized Algebraic Data Types (GADTs) allow precise type specification.

  • Type-safe DSLs: Domain specific languages
  • Better Type Inference: More precise types
  • Expressiveness: More powerful than regular ADTs
haskell
// Haskell Q26: What are GADTs?
"Generalized Algebraic Data Types (GADTs) allow precise type specification:

GADT Syntax:
data Gadt a where
  Constructor :: Type -> Gadt Type

Benefits:
1. Type-safe DSLs
2. Better type inference
3. More expressive types

Examples:
-- Simple GADT
data Expr a where
  IntLit :: Int -> Expr Int
  BoolLit :: Bool -> Expr Bool
  Add :: Expr Int -> Expr Int -> Expr Int
  If :: Expr Bool -> Expr a -> Expr a -> Expr a

-- Type-safe evaluation
eval :: Expr a -> a
eval (IntLit n) = n
eval (BoolLit b) = b
eval (Add e1 e2) = eval e1 + eval e2
eval (If cond e1 e2) = if eval cond then eval e1 else eval e2

-- Using GADT for lists with types
data List a where
  Nil :: List a
  Cons :: a -> List a -> List a

-- Type-safe equality
data Equal a b where
  Refl :: Equal a a

cast :: Equal a b -> a -> b
cast Refl x = x"
Advanced
27. What are phantom types?

Phantom types are type parameters not used in data constructors.

  • Type Safety: Enforce constraints at compile time
  • Documentation: Document intent
  • Use Cases: Units, validation, state machines
haskell
// Haskell Q27: What are phantom types?
"Phantom types are type parameters not used in data constructors:

Phantom Type Definition:
data Phantom a = PhantomValue

Benefits:
1. Type safety at compile time
2. Enforce constraints
3. Document intent

Examples:
-- Phantom type for units
data Meters
data Kilometers

data Distance a = Distance Double

toMeters :: Distance Kilometers -> Distance Meters
toMeters (Distance km) = Distance (km * 1000)

-- Phantom type for validation
data Validated
data Unvalidated

data User a = User { name :: String, age :: Int }

validateUser :: User Unvalidated -> Maybe (User Validated)
validateUser user = if age user >= 18 then Just user else Nothing

-- Phantom type for state
data Unlocked
data Locked

data Door s = Door { isOpen :: Bool }

openDoor :: Door Locked -> Door Unlocked
openDoor (Door _) = Door True

-- Type-safe file operations
data Open
data Closed

data FileHandle s = FileHandle String

openFile :: String -> FileHandle Open
closeFile :: FileHandle Open -> FileHandle Closed"
Intermediate
28. What is the difference between $ and . in Haskell?

$ (function application) and . (function composition) serve different purposes.

  • $: Applies function to argument, low precedence
  • .: Composes two functions, high precedence
  • Use: $ for chaining, . for composition
haskell
// Haskell Q28: What is the difference between $ and . in Haskell?
"$ (function application) and . (function composition) are different:

$ (application):
- Applies function to argument
- Low precedence, right associative
- Helps avoid parentheses
- Function: ($) :: (a -> b) -> a -> b

. (composition):
- Composes two functions
- High precedence, right associative
- Creates new function
- Function: (.) :: (b -> c) -> (a -> b) -> a -> c

Examples:
-- Without $ (needs parentheses)
sum (map (*2) (filter even [1..10]))

-- With $ (no parentheses)
sum $ map (*2) $ filter even [1..10]

-- Function composition
f = sqrt . abs . negate  -- Composition
f 5  -- sqrt (abs (-5))

-- Combining $ and .
process = sum . map (*2) . filter even
result = process [1..10]

-- More examples
map (\x -> x + 1) [1,2,3]  -- Without $
map (+1) [1,2,3]  -- Using operator section

-- $ for chaining
doSomething = head . sort . map sqrt $ filter (>0) [1..10]

-- $ vs .
-- $: f $ x = f x
-- .: (f . g) x = f (g x)"
Beginner
29. What are guards?

Guards are a way to conditionally select function definitions.

  • Conditional Logic: Multiple conditions
  • Pattern Matching: With conditions
  • otherwise: Default case
haskell
// Haskell Q29: What are guards?
"Guards are a way to conditionally select function definitions:

Guard Syntax:
functionName pattern
  | condition1 = result1
  | condition2 = result2
  | otherwise = default

Benefits:
1. Clean conditional logic
2. Pattern matching with conditions
3. Better readability

Examples:
-- Basic guards
max :: Ord a => a -> a -> a
max x y
  | x > y     = x
  | otherwise = y

-- Multiple guards
grade :: Int -> String
grade score
  | score >= 90 = "A"
  | score >= 80 = "B"
  | score >= 70 = "C"
  | score >= 60 = "D"
  | otherwise   = "F"

-- Guards with pattern matching
describeList :: [Int] -> String
describeList [] = "Empty"
describeList (x:xs)
  | x == 0    = "Starts with zero"
  | length xs > 3 = "Long list"
  | otherwise = "Normal list"

-- Guards in do notation
processInput :: IO ()
processInput = do
  line <- getLine
  let n = read line
  putStrLn $ case n of
    _ | n < 0  -> "Negative"
      | n == 0 -> "Zero"
      | n > 0  -> "Positive"

-- Guards with where
discriminant :: Float -> Float -> Float -> Float
discriminant a b c = b^2 - 4*a*c

roots :: Float -> Float -> Float -> (Float, Float)
roots a b c
  | d < 0     = error "No real roots"
  | otherwise = ((-b + sqrt d) / (2*a), (-b - sqrt d) / (2*a))
  where d = discriminant a b c"
Beginner
30. What are modules and how do you import them?

Modules organize code and control visibility.

  • module: Define module
  • import: Import module
  • qualified: Qualified import
  • hiding: Hide specific exports
haskell
// Haskell Q30: What are modules and how do you import them?
"Modules organize code and control visibility:

Module Syntax:
module ModuleName (exports) where
  -- code

Import Syntax:
import ModuleName
import qualified ModuleName as Alias
import ModuleName (function1, function2)

Benefits:
1. Code organization
2. Name space management
3. Information hiding
4. Reusability

Examples:
-- Defining a module
module MyModule (myFunction, MyType(..)) where
  data MyType = Constructor1 | Constructor2
  myFunction = ...

-- Exporting only certain functions
module Math (add, multiply) where
  add :: Int -> Int -> Int
  add x y = x + y
  multiply :: Int -> Int -> Int
  multiply x y = x * y

-- Import examples
import Data.List  -- Import everything
import qualified Data.Map as Map  -- Qualified import
import Data.Text (pack, unpack)  -- Specific imports

-- Common imports
import Control.Monad
import Control.Monad.State
import Data.Maybe
import System.IO

-- Module visibility
module A (publicFunction) where
  privateFunction = ...
  publicFunction = privateFunction + 1

-- Importing modules with same name
import qualified Data.Map as Map
import qualified Data.HashMap as HashMap

-- Using imported functions
main :: IO ()
main = do
  let m = Map.fromList [(1,"one"), (2,"two")]
  print (Map.lookup 1 m)"
Beginner
31. What is the difference between list and tuple?

Lists and tuples serve different purposes in Haskell.

  • Lists: Homogeneous, variable length
  • Tuples: Heterogeneous, fixed length
  • Operations: Different operations for each
haskell
// Haskell Q31: What is the difference between list and tuple?
"Lists and tuples serve different purposes:

Lists:
- Homogeneous (same type)
- Variable length
- Can be infinite
- Operations: head, tail, map, filter
- Syntax: [1,2,3]

Tuples:
- Heterogeneous (different types)
- Fixed length
- Finite
- Operations: fst, snd
- Syntax: (1, "hello", True)

Examples:
-- Lists
list1 = [1,2,3,4,5]  -- All Ints
list2 = ["a","b","c"]  -- All Strings
list3 = [1..]  -- Infinite list

-- Tuples
tuple1 = (1, "hello", True)  -- Different types
tuple2 = (2.5, 'a', "world")  -- Different types

-- List operations
head [1,2,3]  -- 1
tail [1,2,3]  -- [2,3]
map (*2) [1,2,3]  -- [2,4,6]

-- Tuple operations
fst (1, "hello")  -- 1
snd (1, "hello")  -- "hello"

-- Pattern matching
sumList (x:xs) = x + sumList xs
sumTuple (x, y) = x + y

-- List comprehensions
[x*2 | x <- [1..10], x `mod` 2 == 0]  -- [4,8,12,16,20]

-- When to use each
-- List: Multiple items of same type, operations needed
-- Tuple: Fixed number of items of different types"
Beginner
32. What are list comprehensions?

List comprehensions provide a concise way to create lists.

  • Generator: variable <- list
  • Guards: Conditions
  • Expression: What to produce
haskell
// Haskell Q32: What are list comprehensions?
"List comprehensions provide a concise way to create lists:

List Comprehension Syntax:
[expression | variable <- list, condition]

Components:
1. Generator: variable <- list
2. Guards: condition
3. Expression: What to produce

Benefits:
1. Concise syntax
2. Readable
3. Declarative style

Examples:
-- Basic comprehension
[x*2 | x <- [1..10]]  -- [2,4,6,8,10,12,14,16,18,20]

-- With guards
[x*2 | x <- [1..10], x `mod` 2 == 0]  -- [4,8,12,16,20]

-- Multiple generators
[(x,y) | x <- [1,2,3], y <- ['a','b']]  -- [(1,'a'),(1,'b'),...]

-- Nested comprehensions
[[x*y | y <- [1..3]] | x <- [1..3]]  -- [[1,2,3],[2,4,6],[3,6,9]]

-- Pattern matching
[(x,y) | (x,y) <- [(1,2),(3,4),(5,6)], x < y]  -- [(1,2),(3,4),(5,6)]

-- Complex example
pythagoreanTriples :: [(Int, Int, Int)]
pythagoreanTriples = [(a,b,c) | a <- [1..20], b <- [a..20], c <- [b..20], a^2 + b^2 == c^2]

-- String processing
uppercaseLetters = [toUpper c | c <- "hello world", c /= ' ']  -- "HELLOWORLD"

-- With local variables
squares = [x | x <- [1..10], let y = x^2, y > 20]  -- [5,6,7,8,9,10]"
Intermediate
33. What is the difference between map and fold?

map and fold serve different purposes in list processing.

  • map: Applies function to every element
  • fold: Reduces list to single value
  • Use: map for transformation, fold for accumulation
haskell
// Haskell Q33: What is the difference between map and fold?
"map and fold serve different purposes:

map:
- Applies function to every element
- Preserves structure
- Returns same length list
- Type: (a -> b) -> [a] -> [b]

fold:
- Reduces list to single value
- Accumulates results
- Can change length
- Type: (b -> a -> b) -> b -> [a] -> b

Examples:
-- map examples
map (*2) [1,2,3,4]  -- [2,4,6,8]
map (+1) [1,2,3]  -- [2,3,4]
map (\x -> x > 3) [1,2,3,4]  -- [False,False,False,True]

-- fold examples
foldl (+) 0 [1,2,3,4]  -- 10
foldr (*) 1 [1,2,3,4]  -- 24
foldl (\acc x -> acc ++ [x]) [] [1,2,3]  -- [1,2,3]

-- Combining map and fold
sumOfSquares = foldl (+) 0 . map (^2)
sumOfSquares [1,2,3,4]  -- 30

-- Different fold operations
-- foldl: left fold (lazy)
-- foldr: right fold (lazy)
-- foldl': left fold (strict)

-- Practical example
countEven = length . filter even
totalEvenSum = foldl (+) 0 . filter even

-- Map with multiple arguments
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (+) [1,2,3] [4,5,6]  -- [5,7,9]"
Intermediate
34. What are infinite data structures?

Infinite data structures represent potentially unbounded data using lazy evaluation.

  • Lazy Evaluation: Enables infinite structures
  • Only Compute: What's needed
  • Elegant: Solutions for sequences
haskell
// Haskell Q34: What are infinite data structures?
"Infinite data structures represent potentially unbounded data:

Benefits:
1. Lazy evaluation enables infinite structures
2. Only compute what's needed
3. Elegant solutions for sequences

Examples:
-- Infinite list of ones
ones = 1 : ones
take 5 ones  -- [1,1,1,1,1]

-- Infinite list of numbers
nats = [1..]
take 10 nats  -- [1,2,3,4,5,6,7,8,9,10]

-- Fibonacci sequence
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
take 10 fibs  -- [0,1,1,2,3,5,8,13,21,34]

-- Infinite list of primes
primes = sieve [2..]
  where sieve (p:xs) = p : sieve [x | x <- xs, x `mod` p /= 0]
take 10 primes  -- [2,3,5,7,11,13,17,19,23,29]

-- Infinite tree
data Tree a = Node a (Tree a) (Tree a)

infiniteTree = Node 1 infiniteTree infiniteTree

-- Working with infinite lists
takeWhile (<100) [1..]  -- [1..99]
filter even [1..] !! 100  -- 202

-- Lazy evaluation in action
firstMultiple = head [x | x <- [1..], x `mod` 7 == 0, x > 100]  -- 105

-- Stream processing
stream = map (*2) [1..]
take 5 stream  -- [2,4,6,8,10]"
Beginner
35. What is the difference between null, empty, and empty list?

Different ways to represent emptiness in Haskell.

  • null: Function that tests if list is empty
  • empty: Not standard, used in custom types
  • Empty List: [] represents empty list
haskell
// Haskell Q35: What is the difference between null, empty, and empty list?
"Different ways to represent emptiness:

null:
- Function that tests if a list is empty
- Type: [a] -> Bool
- Returns True for empty list

empty:
- Not a standard function in Haskell
- Sometimes used in custom data types
- Often replaced by null

Empty List ([]):
- Represents an empty list
- Used in pattern matching
- Type: [a]

Examples:
-- Using null
null []  -- True
null [1,2,3]  -- False
null "hello"  -- False
null ""  -- True

-- Pattern matching with empty list
head' :: [a] -> a
head' (x:_) = x
head' [] = error "Empty list"

-- Checking length
isEmpty = (== 0) . length
isEmpty []  -- True
isEmpty [1]  -- False

-- Using empty list in functions
sum' [] = 0
sum' (x:xs) = x + sum' xs

-- Maybe type with empty
data Maybe a = Nothing | Just a

fromMaybe :: a -> Maybe a -> a
fromMaybe default Nothing = default
fromMaybe _ (Just x) = x

-- Different representations of nothing
nothing1 = [] :: [Int]
nothing2 = Nothing :: Maybe Int
nothing3 = "" :: String

-- Checking emptiness in different contexts
caseMaybe :: Maybe a -> String
caseMaybe Nothing = "Nothing"
caseMaybe (Just _) = "Something"
Beginner
36. What are type annotations?

Type annotations explicitly specify types in Haskell.

  • Documentation: Clear type signatures
  • Type Safety: Better error messages
  • Guideline: For type inference
haskell
// Haskell Q36: What are type annotations?
"Type annotations explicitly specify types:

Type Annotation Syntax:
expression :: Type

Benefits:
1. Documentation
2. Type safety
3. Better error messages
4. Guideline for type inference

Examples:
-- Basic type annotations
x :: Int
x = 5

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

-- Function type annotations
square :: Num a => a -> a
square x = x * x

-- Polymorphic type annotation
identity :: a -> a
identity x = x

-- With type constraints
max' :: Ord a => a -> a -> a
max' x y = if x > y then x else y

-- Complex type annotations
map' :: (a -> b) -> [a] -> [b]
map' _ [] = []
map' f (x:xs) = f x : map' f xs

-- Type annotations for clarification
process :: [Int] -> Int
process xs = foldl (+) 0 (filter (>0) xs)

-- Type annotations in where clauses
calculate x y = result
  where
    result :: Int
    result = x + y

-- Type annotations with type classes
printValue :: Show a => a -> IO ()
printValue x = putStrLn (show x)

-- Scoped type variables
{-# LANGUAGE ScopedTypeVariables #-}
f :: forall a. [a] -> [a]
f (x:xs) = [x] ++ rest
  where
    rest :: [a]
    rest = xs"
Advanced
37. What are type families?

Type families define type-level functions.

  • Type-level Computation: Compute types
  • Flexible: Type definitions
  • Abstraction: Better abstraction
haskell
// Haskell Q37: What are type families?
"Type families define type-level functions:

Type Family Syntax:
type family Name a :: *

Benefits:
1. Type-level computation
2. Flexible type definitions
3. Better abstraction

Examples:
-- Type family declaration
type family Element t :: *
type instance Element [a] = a
type instance Element (Maybe a) = a

-- Using type families
getElement :: Element [Int] -> Int
getElement x = x

-- Associated type families
class Collection c where
  type Element c
  toList :: c -> [Element c]

instance Collection [a] where
  type Element [a] = a
  toList = id

-- Data type family
data family Vector a
data instance Vector Int = IntVector [Int]
data instance Vector Char = CharVector [Char]

-- Closed type families
type family IsString a :: Bool where
  IsString [Char] = True
  IsString a = False

-- Using closed family
showIfString :: IsString a ~ True => a -> String
showIfString x = show x

-- Type family with parameters
type family Add a b :: *
type instance Add Int Int = Int
type instance Add Double Double = Double

-- Type family in class
class Convert a b where
  convert :: a -> b"
Advanced
38. What are existential types?

Existential types hide internal implementation details.

  • Information Hiding: Hide implementation
  • Abstract Data Types: Abstract interfaces
  • Heterogeneous Collections: Different types together
haskell
// Haskell Q38: What are existential types?
"Existential types hide internal implementation details:

Existential Type Syntax:
data Exists = forall a. Exists a

Benefits:
1. Information hiding
2. Abstract data types
3. Heterogeneous collections

Examples:
-- Basic existential
data Showable = forall a. Show a => Showable a

instance Show Showable where
  show (Showable x) = show x

-- Using Showable
collection :: [Showable]
collection = [Showable 5, Showable "hello", Showable 3.14]

-- Heterogeneous list with operations
data AnyList = forall a. AnyList [a]

headAny :: AnyList -> Maybe AnyList
headAny (AnyList (x:xs)) = Just (AnyList [x])
headAny (AnyList []) = Nothing

-- Existential with constraints
data Shape = forall s. Shape s
  where Shape :: (Drawable s, Area s) => s -> Shape

class Drawable s where
  draw :: s -> String

class Area s where
  area :: s -> Float

-- Using GADTs for existential
data Expr where
  Expr :: (Show a) => a -> Expr

-- Practical example
data Employee = forall a. (Workable a, Payable a) => Employee a

class Workable a where
  work :: a -> String

class Payable a where
  salary :: a -> Double

-- List of different types
employees :: [Employee]
employees = [Employee manager, Employee developer, Employee designer]"
Advanced
39. What are kind and sort?

Kinds are the 'types of types' in Haskell.

  • *: Type of concrete types
  • * -> *: Type constructor
  • (* -> *) -> *: Higher-kinded type
haskell
// Haskell Q39: What are kind and sort?
"Kinds are the 'types of types':

Kind Hierarchy:
1. * : Type of concrete types
2. * -> * : Type constructor
3. (* -> *) -> * : Higher-kinded type

Examples:
-- Basic kinds
Int :: *  -- Concrete type
Maybe :: * -> *  -- Type constructor

-- Kind signatures
data Maybe a = Nothing | Just a  -- Maybe :: * -> *

data Pair a b = Pair a b  -- Pair :: * -> * -> *

-- Higher-kinded types
class Functor f where
  fmap :: (a -> b) -> f a -> f b
-- Functor :: (* -> *) -> Constraint

-- Kind annotations
data List a = Nil | Cons a (List a)  -- List :: * -> *

-- Using kinds
data Applicative f = Applicative
  (forall a b. (a -> b) -> f a -> f b)
  (forall a. a -> f a)

-- Kind polymorphism
{-# LANGUAGE PolyKinds #-}
data Proxy (a :: k) = Proxy

-- Higher-kinded data
data Free f a = Pure a | Free (f (Free f a))

-- Kind inference
-- Without annotation:
data T a = T a  -- T :: * -> *

-- With explicit kind
data T (a :: *) = T a

-- Kind of type classes
class Eq a where  -- Eq :: * -> Constraint
  (==) :: a -> a -> Bool"
Advanced
40. What are the differences between monad, applicative, and functor?

The hierarchy of abstraction from least to most powerful.

  • Functor: Maps functions, no sequencing
  • Applicative: Sequential application, no dependencies
  • Monad: Sequential composition with dependencies
haskell
// Haskell Q40: What are the differences between monad, applicative, and functor?
"The hierarchy of abstraction from least to most powerful:

Functor:
- Maps functions over context
- fmap :: (a -> b) -> f a -> f b
- Preserves structure
- No sequencing

Applicative:
- Applies functions in context
- pure :: a -> f a
- (<*>) :: f (a -> b) -> f a -> f b
- Sequencing without dependency

Monad:
- Chains computations with dependency
- return :: a -> m a
- (>>=) :: m a -> (a -> m b) -> m b
- Sequencing with dependency

Examples:
-- Functor
fmap (*2) (Just 3)  -- Just 6
fmap show [1,2,3]  -- ["1","2","3"]

-- Applicative
Just (+3) <*> Just 5  -- Just 8
(*) <$> [1,2] <*> [3,4]  -- [3,4,6,8]

-- Monad
Just 3 >>= \x -> Just (x + 5)  -- Just 8
[1,2] >>= \x -> [x, x*2]  -- [1,2,2,4]

-- Comparison
-- Functor: fmap f x = pure f <*> x = do { a <- x; return (f a) }
-- Applicative: pure f <*> x = do { f' <- pure f; f' <*> x }
-- Monad: x >>= f = join (fmap f x)

-- When to use which
-- Functor: Map over a value in context
-- Applicative: Apply multiple functions in context
-- Monad: Chain dependent computations"
Intermediate
41. What is the difference between Data.List and Prelude?

Prelude and Data.List provide different functionality.

  • Prelude: Basic list functions
  • Data.List: Extended list functions
  • Import: Data.List must be imported
haskell
// Haskell Q41: What is the difference between Data.List and Prelude?
"Prelude and Data.List provide different functionality:

Prelude:
- Automatically imported
- Basic list functions
- Minimal functionality
- Designed for everyday use

Data.List:
- Must be imported
- Extended list functions
- Advanced operations
- More specialized functions

Examples:
-- Prelude functions
head, tail, init, last, map, filter, foldl, foldr, length, (++), (!!)

-- Data.List functions
import Data.List

-- Intercalate
intercalate ", " ["hello", "world"]  -- "hello, world"

-- Group
group [1,1,2,2,3,3]  -- [[1,1],[2,2],[3,3]]

-- Sort
sort [3,1,4,1,5,9]  -- [1,1,3,4,5,9]

-- Nub (unique)
nub [1,2,1,3,2]  -- [1,2,3]

-- Inits and tails
inits [1,2,3]  -- [[],[1],[1,2],[1,2,3]]
tails [1,2,3]  -- [[1,2,3],[2,3],[3],[]]

-- Strip prefixes
stripPrefix "hello" "helloworld"  -- Just "world"

-- Subsequences
subsequences [1,2,3]  -- [[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]

-- Permutations
permutations [1,2,3]  -- [[1,2,3],[2,1,3],[3,1,2],[1,3,2],[2,3,1],[3,2,1]]

-- Partitions
partition (>3) [1..10]  -- ([4,5,6,7,8,9,10],[1,2,3])

-- When to use each
-- Prelude: Basic operations
-- Data.List: Advanced operations"
Advanced
42. What is the StateT monad transformer?

StateT combines State with another monad.

  • runStateT: Run the transformer
  • evalStateT: Get result only
  • execStateT: Get state only
  • lift: Lift base monad operations
haskell
// Haskell Q42: What is the StateT monad transformer?
"StateT combines State with another monad:

StateT Definition:
newtype StateT s m a = StateT { runStateT :: s -> m (a, s) }

Key Functions:
1. runStateT: Run the transformer
2. evalStateT: Get result only
3. execStateT: Get state only
4. lift: Lift base monad operations

Examples:
import Control.Monad.State
import Control.Monad.Trans.State

-- Type definition
type StateM a = StateT AppState IO a

data AppState = AppState { counter :: Int, log :: [String] }

-- Basic operations
increment :: StateM ()
increment = do
  modify (\s -> s { counter = counter s + 1 })
  state <- get
  liftIO (putStrLn ("Counter: " ++ show (counter state)))

-- Complex operation
process :: Int -> StateM Int
process n = do
  increment
  state <- get
  let newState = state { log = ("Processing " ++ show n) : log state }
  put newState
  liftIO (putStrLn ("Logged: " ++ show (log state)))
  return (n * 2)

-- Running StateT
main :: IO ()
main = do
  let initialState = AppState { counter = 0, log = [] }
  result <- runStateT (process 10) initialState
  print result

-- Using with MaybeT
type MyMonad = StateT Int (MaybeT IO)

-- Using with ReaderT
type AppMonad = StateT AppState (ReaderT Config IO)

-- Lifting operations
liftIO :: IO a -> StateT s IO a
liftIO = Control.Monad.Trans.State.liftIO

-- Pattern matching in StateT
runAll :: StateT Int IO ()
runAll = do
  n <- get
  when (n > 0) $ do
    put (n - 1)
    liftIO (print n)
    runAll"
Advanced
43. What are MonadFail and MonadIO?

MonadFail handles failure, MonadIO lifts IO operations.

  • MonadFail: Pattern match failures
  • MonadIO: Lift IO operations
  • Use: Monad transformers
haskell
// Haskell Q43: What are MonadFail and MonadIO?
"MonadFail handles failure in monads, MonadIO lifts IO operations:

MonadFail:
- Handles pattern match failures
- Provides fail function
- Used in do notation

MonadIO:
- Lifts IO operations
- Provides liftIO function
- Used with transformers

Examples:
import Control.Monad.Fail
import Control.Monad.IO.Class

-- MonadFail instance
data MyMonad a = Success a | Failure String

instance MonadFail MyMonad where
  fail msg = Failure msg

-- Using MonadFail in do notation
safeDiv :: MonadFail m => Int -> Int -> m Int
safeDiv _ 0 = fail "Division by zero"
safeDiv x y = return (x `div` y)

-- MonadIO example
type AppM = ReaderT Config (StateT State IO)

logMessage :: MonadIO m => String -> m ()
logMessage msg = liftIO (putStrLn msg)

-- Using MonadIO
process :: (MonadIO m, MonadState AppState m) => m ()
process = do
  liftIO (putStrLn "Starting")
  modify (\s -> s { counter = counter s + 1 })
  liftIO (putStrLn "Incremented")

-- MonadFail with transformers
type App = ReaderT Config (StateT State (ExceptT String IO))

failExample :: App Int
failExample = do
  config <- ask
  if config == "debug"
    then return 42
    else fail "Invalid config"

-- Combining MonadIO and MonadFail
safeIO :: (MonadIO m, MonadFail m) => String -> m String
safeIO path = do
  content <- liftIO (readFile path)
  if null content
    then fail "Empty file"
    else return content"
Advanced
44. What are arrows?

Arrows generalize functions and monads.

  • Generalization: More general than monads
  • Circuit-like: Computations
  • Static Analysis: Possible
haskell
// Haskell Q44: What are arrows?
"Arrows generalize functions and monads:

Arrow Definition:
class Category a => Arrow a where
  arr :: (b -> c) -> a b c
  first :: a b c -> a (b, d) (c, d)

Benefits:
1. More general than monads
2. Circuit-like computations
3. Static analysis possible

Examples:
import Control.Arrow

-- Basic arrow operations
addOne :: Arrow a => a Int Int
addOne = arr (+1)

-- Combining arrows
process = arr (+1) >>> arr (*2)

-- Arrow composition
f = arr (^2) >>> arr (+1)  -- f x = x^2 + 1

-- Arrow with first
swap = arr (\ (x,y) -> (y,x))
addPairs = arr (\ (x,y) -> x + y)

-- Arrow loop
loopExample = loop (arr (\ (x,y) -> (y, x+y)))

-- Kliesli arrows
type Kliesli m a b = a -> m b

-- Arrow with state
newtype StateArrow s a b = StateArrow ((s,a) -> (s,b))

instance Arrow (StateArrow s) where
  arr f = StateArrow (\ (s,x) -> (s, f x))
  first (StateArrow f) = StateArrow (\ (s, (x,y)) -> 
    let (s', x') = f (s,x)
    in (s', (x',y)))

-- Practical arrow example
data Circuit a b = Circuit (a -> (Circuit a b, b))

instance Arrow Circuit where
  arr f = Circuit (\x -> (arr f, f x))
  first (Circuit f) = Circuit (\ (x,y) -> 
    let (c, x') = f x
    in (first c, (x', y)))

-- Using circuit
counter :: Circuit Int Int
counter = Circuit go
  where go x = (counter, x + 1)"
Advanced
45. What are comonads?

Comonads are the dual of monads.

  • extract: Get value from context
  • duplicate: Duplicate context
  • extend: Extend context
  • Dual: Opposite of monads
haskell
// Haskell Q45: What are comonads?
"Comonads are the dual of monads:

Comonad Definition:
class Functor w => Comonad w where
  extract :: w a -> a
  duplicate :: w a -> w (w a)
  extend :: (w a -> b) -> w a -> w b

Key Laws:
1. extract . duplicate = id
2. fmap extract . duplicate = id
3. duplicate . duplicate = fmap duplicate . duplicate

Examples:
import Control.Comonad

-- List comonad (non-empty list)
data NonEmpty a = a :| [a]

instance Functor NonEmpty where
  fmap f (x :| xs) = f x :| map f xs

instance Comonad NonEmpty where
  extract (x :| _) = x
  duplicate xs = xs :| tails xs

-- Using NonEmpty
tails :: NonEmpty a -> [NonEmpty a]
tails (x :| xs) = (x :| xs) : case xs of
  [] -> []
  (y:ys) -> tails (y :| ys)

-- Stream comonad
data Stream a = Cons a (Stream a)

instance Functor Stream where
  fmap f (Cons x xs) = Cons (f x) (fmap f xs)

instance Comonad Stream where
  extract (Cons x _) = x
  duplicate (Cons x xs) = Cons (Cons x xs) (duplicate xs)

-- Using streams
nats = Cons 1 (fmap (+1) nats)

-- Store comonad
data Store s a = Store (s -> a) s

instance Functor (Store s) where
  fmap f (Store g s) = Store (f . g) s

instance Comonad (Store s) where
  extract (Store f s) = f s
  duplicate (Store f s) = Store (\s' -> Store f s') s

-- Practical example
movingAverage :: Stream Int -> Stream Int
movingAverage = extend (\s -> sum (take 3 (toList s)) `div` 3)
  where toList (Cons x xs) = x : toList xs"
Advanced
46. What are free monads?

Free monads create monads from functors.

  • DSLs: Build domain-specific languages
  • Syntax/Semantics: Separate from interpretation
  • Composition: Compose effects
haskell
// Haskell Q46: What are free monads?
"Free monads create monads from functors:

Free Monad Definition:
data Free f a = Pure a | Free (f (Free f a))

Benefits:
1. Build DSLs
2. Separate syntax from semantics
3. Composition of effects

Examples:
import Control.Monad.Free

-- Simple DSL
data Teletype a = PutStrLn String a | GetLine (String -> a)

instance Functor Teletype where
  fmap f (PutStrLn s x) = PutStrLn s (f x)
  fmap f (GetLine g) = GetLine (f . g)

type Program = Free Teletype

-- Smart constructors
putStrLn' :: String -> Program ()
putStrLn' s = liftF (PutStrLn s ())

getLine' :: Program String
getLine' = liftF (GetLine id)

-- Example program
hello :: Program ()
hello = do
  putStrLn' "What's your name?"
  name <- getLine'
  putStrLn' ("Hello, " ++ name)

-- Interpreter
runTeletype :: Program () -> IO ()
runTeletype (Pure ()) = return ()
runTeletype (Free (PutStrLn s next)) = do
  putStrLn s
  runTeletype next
runTeletype (Free (GetLine f)) = do
  line <- getLine
  runTeletype (f line)

-- Free monad for state
data StateF s a = Get (s -> a) | Put s a

instance Functor (StateF s) where
  fmap f (Get g) = Get (f . g)
  fmap f (Put s a) = Put s (f a)

type StateFree s = Free (StateF s)

get :: StateFree s s
get = liftF (Get id)

put :: s -> StateFree s ()
put s = liftF (Put s ())

modify :: (s -> s) -> StateFree s ()
modify f = do
  s <- get
  put (f s)"
Advanced
47. What are monad laws?

Monad laws ensure consistent behavior.

  • Left Identity: return a >>= f = f a
  • Right Identity: m >>= return = m
  • Associativity: (m >>= f) >>= g = m >>= (x -> f x >>= g)
haskell
// Haskell Q47: What are monad laws?
"Monad laws ensure consistent behavior:

Three Laws:
1. Left Identity: return a >>= f = f a
2. Right Identity: m >>= return = m
3. Associativity: (m >>= f) >>= g = m >>= (\x -> f x >>= g)

Examples:
-- Testing monad laws with Maybe
leftIdentity :: (a -> Maybe a) -> a -> Bool
leftIdentity f a = (return a >>= f) == f a

rightIdentity :: Maybe a -> Bool
rightIdentity m = (m >>= return) == m

associativity :: Maybe a -> (a -> Maybe b) -> (b -> Maybe c) -> Bool
associativity m f g = 
  ((m >>= f) >>= g) == (m >>= (\x -> f x >>= g))

-- List monad laws
leftIdentityList f a = [a] >>= f == f a
rightIdentityList xs = xs >>= return == xs
associativityList xs f g = 
  (xs >>= f) >>= g == xs >>= (\x -> f x >>= g)

-- Why laws matter
-- Without laws, code would be unpredictable
-- Laws enable reasoning about code
-- Laws support refactoring

-- Monad instance checking
-- Maybe monad violates? No, follows all laws
-- List monad follows all laws
-- IO monad follows all laws (in theory)

-- Practical implications
-- You can refactor: do { x <- m; f x } to m >>= f
-- You can reorder: return x >>= f = f x"
Advanced
48. What is the difference between foldr and foldl in terms of laziness?

foldr and foldl differ in evaluation strategy.

  • foldr: Lazy, works with infinite lists
  • foldl: Strict, can overflow stack
  • foldl': Strict left fold (recommended)
haskell
// Haskell Q48: What is the difference between foldr and foldl in terms of laziness?
"Foldr and foldl differ in evaluation strategy:

foldr:
- Lazy evaluation
- Works with infinite lists
- Can short-circuit
- Right associative

foldl:
- Lazy evaluation but strict in accumulator
- Doesn't work with infinite lists
- Can cause stack overflow
- Left associative

Examples:
-- foldr with infinite list
foldr (:) [] [1..]  -- Works (lazy)
foldr (+) 0 [1..]  -- Doesn't terminate (strict operation)

-- foldl with infinite list
foldl (+) 0 [1..]  -- Never terminates
foldl (flip (:)) [] [1..]  -- Never terminates

-- Short-circuiting with foldr
anyEven = foldr (\x acc -> even x || acc) False
anyEven [1..]  -- True (stops at first even)

-- foldr with lazy operation
or' = foldr (||) False
or' (False : repeat True)  -- True (lazy)

-- foldl can't short-circuit
orL = foldl (||) False
orL (False : repeat True)  -- Never terminates

-- Memory usage
-- foldr: O(n) stack for lazy operations
-- foldl': O(1) stack for strict operations

-- Choosing the right fold
-- foldr: For lazy operations, infinite lists, constructing data
-- foldl': For strict accumulations, numeric operations
-- foldl: Rarely (use foldl' instead)

-- foldr with strict operation needs strictness
foldr (+) 0 [1..1000000]  -- Possible stack overflow
foldl' (+) 0 [1..1000000]  -- Safe"
Beginner
49. What are data constructors?

Data constructors create values of algebraic data types.

  • Nullary: No arguments
  • Product: Multiple arguments
  • Record: Named fields
  • Recursive: References to same type
haskell
// Haskell Q49: What are data constructors?
"Data constructors create values of algebraic data types:

Types of Constructors:
1. Nullary: No arguments
2. Product: Multiple arguments
3. Record: Named fields
4. Recursive: References to same type

Examples:
-- Nullary constructor
data Bool = False | True

-- Product constructor
data Person = Person String Int

-- Record syntax
data Employee = Employee
  { name :: String
  , age :: Int
  , salary :: Double
  }

-- Recursive constructor
data List a = Nil | Cons a (List a)
data Tree a = Leaf a | Node (Tree a) (Tree a)

-- Multiple constructors with different arguments
data Shape = Circle Float | Rectangle Float Float | Triangle Float Float Float

-- Pattern matching with constructors
area :: Shape -> Float
area (Circle r) = pi * r * r
area (Rectangle w h) = w * h
area (Triangle a b c) = a * b / 2

-- Using record constructors
createEmployee :: Employee
createEmployee = Employee
  { name = "Alice"
  , age = 25
  , salary = 50000
  }

-- Constructor functions
mkPerson :: String -> Int -> Person
mkPerson = Person

-- Data constructor vs type constructor
-- Type constructor: Maybe (takes a type)
-- Data constructor: Just (takes a value)

-- Newtype constructor
newtype Age = Age Int

-- Type aliases vs data constructors
type Name = String  -- No constructor
data Name' = Name String  -- Has constructor"
Intermediate
50. What are record syntax and field accessors?

Record syntax provides named fields and automatic accessors.

  • Named Fields: Field names
  • Accessors: Automatic getter functions
  • Update Syntax: Record update
  • Pattern Matching: With named fields
haskell
// Haskell Q50: What are record syntax and field accessors?
"Record syntax provides named fields and automatic accessors:

Record Syntax:
data Record = Record
  { field1 :: Type1
  , field2 :: Type2
  }

Benefits:
1. Named fields
2. Automatic accessors
3. Update syntax
4. Pattern matching

Examples:
-- Defining record
data Person = Person
  { name :: String
  , age :: Int
  , address :: String
  } deriving (Show)

-- Creating record
alice = Person
  { name = "Alice"
  , age = 25
  , address = "123 Main St"
  }

-- Accessing fields
getName :: Person -> String
getName = name

getAge :: Person -> Int
getAge = age

-- Updating records
bob = alice { name = "Bob", age = 30 }

-- Pattern matching with records
printPerson :: Person -> String
printPerson Person { name = n, age = a } =
  "Name: " ++ n ++ ", Age: " ++ show a

-- Field update with function
incrementAge :: Person -> Person
incrementAge p = p { age = age p + 1 }

-- Multiple updates
updatePerson :: Person -> Person
updatePerson p = p
  { age = age p + 1
  , address = address p ++ " (updated)"
  }

-- Record with complex fields
data Employee = Employee
  { empName :: String
  , empDetails :: Person
  , empSalary :: Double
  }

-- Field access composition
getEmployeeName :: Employee -> String
getEmployeeName = name . empDetails

-- Empty record syntax
data Empty = Empty {}

-- Record with phantom type
data User a = User
  { userName :: String
  , userAge :: Int
  }"
Intermediate
51. What are type variables and polymorphism?

Type variables enable polymorphic functions.

  • Parametric: Same behavior for all types
  • Ad-hoc: Different behavior per type
  • Rank-N: Higher-rank polymorphism
haskell
// Haskell Q51: What are type variables and polymorphism?
"Type variables enable polymorphic functions:

Type Variables:
- Lowercase letters: a, b, c, etc.
- Can be any type
- Enable generic programming

Polymorphism Types:
1. Parametric: Same behavior for all types
2. Ad-hoc: Different behavior per type (type classes)
3. Rank-N: Higher-rank polymorphism

Examples:
-- Parametric polymorphism
identity :: a -> a
identity x = x

-- List functions
length :: [a] -> Int
map :: (a -> b) -> [a] -> [b]

-- Polymorphic data types
data Maybe a = Nothing | Just a
data Either a b = Left a | Right b

-- Ad-hoc polymorphism with type classes
add :: Num a => a -> a -> a
add x y = x + y

-- Comparing values
compare :: Ord a => a -> a -> Ordering

-- Rank-2 polymorphism
{-# LANGUAGE RankNTypes #-}
apply :: (forall a. a -> a) -> Int -> Int
apply f x = f x

-- Type variables in constraints
process :: (Show a, Read a) => a -> String
process x = show x

-- Scoped type variables
{-# LANGUAGE ScopedTypeVariables #-}
f :: forall a. [a] -> [a]
f (x:xs) = [x] ++ (f xs :: [a])

-- Type variable naming conventions
-- a, b, c: Generic types
-- m: Monad
-- f: Functor
-- t: Type
-- s: State"
Intermediate
52. What are constraints and contexts?

Constraints and contexts specify type requirements.

  • Eq: Equality
  • Ord: Ordering
  • Num: Numeric operations
  • Show: String conversion
haskell
// Haskell Q52: What are constraints and contexts?
"Constraints and contexts specify type requirements:

Constraint Syntax:
function :: (Constraint1 a, Constraint2 a) => a -> a

Common Constraints:
1. Eq: Equality
2. Ord: Ordering
3. Num: Numeric operations
4. Show: String conversion
5. Read: Parsing
6. Functor: Mapping
7. Applicative: Sequencing
8. Monad: Chaining

Examples:
-- Multiple constraints
sort :: Ord a => [a] -> [a]

process :: (Show a, Read a) => String -> a
process s = read s

-- Context in data declaration
data Eq a => Set a = Set [a]

-- Constraint in type synonym
type MyType a = (Num a, Show a) => a

-- Constraint in class instance
instance Ord a => Eq (Maybe a) where
  (Just x) == (Just y) = x == y
  _ == _ = False

-- Undecidable instances
{-# LANGUAGE UndecidableInstances #-}
instance (Eq a, Eq b) => Eq (a, b) where
  (x1, y1) == (x2, y2) = x1 == x2 && y1 == y2

-- Constraint kinds
-- Eq a where a has kind *
-- Functor f where f has kind * -> *

-- Using constraints in functions
map' :: Functor f => (a -> b) -> f a -> f b

-- Constraint implication
{-# LANGUAGE ConstraintKinds #-}
type NumLike a = (Num a, Eq a)

add' :: NumLike a => a -> a -> a
add' x y = x + y"
Advanced
53. What are functional dependencies?

Functional dependencies express relationships between types.

  • Type Inference: Better inference
  • Avoid Ambiguity: Clear relationships
  • Type-level: Relationships
haskell
// Haskell Q53: What are functional dependencies?
"Functional dependencies express relationships between types:

Functional Dependency Syntax:
class Class a b | a -> b where ...

Meaning: a determines b

Benefits:
1. Type inference
2. Avoid ambiguity
3. Type-level relationships

Examples:
-- Basic functional dependency
class Convert a b | a -> b where
  convert :: a -> b

instance Convert Int String where
  convert = show

instance Convert String Int where
  convert = read

-- Multi-parameter type class with fundeps
class Collection c e | c -> e where
  empty :: c
  insert :: e -> c -> c
  toList :: c -> [e]

instance Collection [e] e where
  empty = []
  insert x xs = x : xs
  toList = id

-- Using functional dependencies
class HasKey k v | k -> v where
  getValue :: k -> v

-- Functional dependency in practice
class StateMonad m s | m -> s where
  get :: m s
  put :: s -> m ()

-- Multiple dependencies
class Relation a b c | a -> b, a -> c where
  combine :: a -> (b, c)

-- Ambiguity resolution
class Read a where
  readsPrec :: Int -> ReadS a

-- Using fundeps for type-level computation
class Add a b c | a b -> c where
  add :: a -> b -> c

instance Add Int Int Int where
  add = (+)

instance Add Double Double Double where
  add = (+)"
Advanced
54. What are type families vs functional dependencies?

Both solve similar problems with different approaches.

  • Type Families: Type-level functions
  • Functional Dependencies: Express relationships
  • Use: Type Families for computation, Fundeps for relationships
haskell
// Haskell Q54: What are type families vs functional dependencies?
"Both solve similar problems with different approaches:

Type Families:
- Define type-level functions
- More flexible
- Better for large projects

Functional Dependencies:
- Express relationships
- Older approach
- Simpler for small projects

Examples:
-- Type Families
type family Element t :: *
type instance Element [a] = a

class Collection c where
  type Elem c
  empty :: c
  insert :: Elem c -> c -> c

instance Collection [a] where
  type Elem [a] = a
  empty = []
  insert x xs = x : xs

-- Functional Dependencies
class Collection' c e | c -> e where
  empty' :: c
  insert' :: e -> c -> c

instance Collection' [a] a where
  empty' = []
  insert' x xs = x : xs

-- Key differences
-- Type Families: Can compute types
type family Add a b where
  Add Int Int = Int
  Add Double Double = Double

-- Functional Dependencies: Express constraints
class Convert a b | a -> b, b -> a

-- Type Families: Better for open world
type family F a :: *
type instance F Int = Bool
type instance F String = Int

-- Functional Dependencies: Better for closed world
class C a b | a -> b

-- When to use each
-- Type Families: Complex type-level computations
-- Functional Dependencies: Simple type relationships"
Advanced
55. What are associated types?

Associated types are type families inside type classes.

  • Cleaner Syntax: Type-level computation
  • Better Abstraction: In classes
  • Use: Collection types, data structures
haskell
// Haskell Q55: What are associated types?
"Associated types are type families inside type classes:

Associated Type Syntax:
class Class where
  type AssociatedType a :: *

Benefits:
1. Cleaner syntax
2. Type-level computation
3. Better abstraction

Examples:
-- Basic associated type
class Collection c where
  type Element c :: *
  empty :: c
  insert :: Element c -> c -> c

instance Collection [a] where
  type Element [a] = a
  empty = []
  insert x xs = x : xs

-- Multiple associated types
class Map m where
  type Key m :: *
  type Value m :: *
  emptyMap :: m
  insertMap :: Key m -> Value m -> m -> m

instance Map [(k,v)] where
  type Key [(k,v)] = k
  type Value [(k,v)] = v
  emptyMap = []
  insertMap k v m = (k,v) : m

-- Associated type with default
class Container c where
  type Item c :: *
  type Item c = c  -- Default

-- Associated type in GADT
class Show a where
  type ShowS a :: *

-- Using associated types
class HasName a where
  type Name a :: *
  getName :: a -> Name a

instance HasName Person where
  type Name Person = String
  getName = personName

-- Associated type with constraints
class Serializable a where
  type Serialized a :: *
  serialize :: a -> Serialized a
  deserialize :: Serialized a -> a"
Advanced
56. What are closed type families?

Closed type families have a fixed set of instances.

  • Exhaustive: Pattern matching
  • Type-level: Computation
  • No Overlap: Issues
haskell
// Haskell Q56: What are closed type families?
"Closed type families have a fixed set of instances:

Closed Type Family Syntax:
type family Name a where
  Name Type1 = Result1
  Name Type2 = Result2

Benefits:
1. Exhaustive pattern matching
2. Type-level computation
3. No overlapping issues

Examples:
-- Basic closed family
type family IsString a where
  IsString [Char] = True
  IsString a = False

-- Type-level arithmetic
type family Add a b where
  Add Zero b = b
  Add (Succ a) b = Succ (Add a b)

-- Peano numbers
data Zero = Zero
data Succ n = Succ n

-- Type-level comparison
type family Compare a b where
  Compare Zero Zero = EQ
  Compare Zero (Succ a) = LT
  Compare (Succ a) Zero = GT
  Compare (Succ a) (Succ b) = Compare a b

-- Type-level boolean operations
type family And a b where
  And True True = True
  And a b = False

type family Or a b where
  Or False False = False
  Or a b = True

-- Type-level lists
type family Concat xs ys where
  Concat '[] ys = ys
  Concat (x ': xs) ys = x ': Concat xs ys

-- Type-level length
type family Length xs where
  Length '[] = Zero
  Length (x ': xs) = Succ (Length xs)

-- Closed family with overlapping
-- Earlier patterns take precedence
type family Priority a where
  Priority Int = 1
  Priority a = 0"
Advanced
57. What are data families?

Data families define type-indexed data types.

  • Type-indexed: Data indexed by type
  • Flexible: Different representations
  • Type Safety: Compile-time guarantees
haskell
// Haskell Q57: What are data families?
"Data families define type-indexed data types:

Data Family Syntax:
data family Name a :: *

Benefits:
1. Type-indexed data
2. Flexible representations
3. Type safety

Examples:
-- Basic data family
data family Vector a

data instance Vector Int = IntVector [Int]
data instance Vector Char = CharVector [Char]
data instance Vector Bool = BoolVector [Bool]

-- Using vector
processInt :: Vector Int -> Int
processInt (IntVector xs) = sum xs

-- Multiple parameters
data family Tree a b

data instance Tree Int String = Node String (Tree Int String)

-- GADT-style data family
data instance Maybe a where
  Nothing :: Maybe a
  Just :: a -> Maybe a

-- Associated data families
class Collection c where
  data Elem c :: *
  empty :: c
  insert :: Elem c -> c -> c

instance Collection [a] where
  data Elem [a] = Elem a
  empty = []
  insert (Elem x) xs = x : xs

-- Data family with constraints
data family Ord a => Set a

data instance Ord a => Set a = Set [a]

-- Using data families
data Family a where
  Family :: (Show a) => a -> Family a

-- Pattern matching on data families
processFamily :: Family a -> String
processFamily (Family x) = show x"
Advanced
58. What are GADT syntax extensions?

GADTs extend Haskell's data type syntax.

  • GADTs: General ADTs
  • GADTSyntax: Alternate syntax
  • ExistentialQuantification: Existential types
haskell
// Haskell Q58: What are GADT syntax extensions?
"GADTs extend Haskell's data type syntax:

GADT Syntax:
data MyType a where
  Constructor :: Type -> MyType Type

Extensions:
1. GADTs: General ADTs
2. GADTSyntax: Alternate syntax
3. ExistentialQuantification: Existential types

Examples:
-- Basic GADT
{-# LANGUAGE GADTs #-}
data Expr a where
  IntLit :: Int -> Expr Int
  BoolLit :: Bool -> Expr Bool
  Add :: Expr Int -> Expr Int -> Expr Int
  If :: Expr Bool -> Expr a -> Expr a -> Expr a

-- Type-safe eval
eval :: Expr a -> a
eval (IntLit n) = n
eval (BoolLit b) = b
eval (Add e1 e2) = eval e1 + eval e2
eval (If cond e1 e2) = if eval cond then eval e1 else eval e2

-- GADT for list with type info
data List a where
  Nil :: List a
  Cons :: a -> List a -> List a

-- Type-safe equality
data EqProof a b where
  Refl :: EqProof a a

cast :: EqProof a b -> a -> b
cast Refl x = x

-- GADT with constraints
data Showable where
  Showable :: (Show a) => a -> Showable

-- GADT for typed AST
data Typed a where
  TInt :: Int -> Typed Int
  TBool :: Bool -> Typed Bool
  TIf :: Typed Bool -> Typed a -> Typed a -> Typed a

-- GADT for state machines
data State a where
  Init :: State Init
  Running :: State Running
  Done :: State Done

-- Using GADT for DSL
data DSL a where
  Print :: String -> DSL ()
  Read :: DSL String
  Bind :: DSL a -> (a -> DSL b) -> DSL b"
Advanced
59. What are existential types in GADTs?

GADTs naturally support existential types.

  • Type Hiding: Hide implementation
  • Abstract Data Types: Abstract interfaces
  • Heterogeneous Collections: Different types together
haskell
// Haskell Q59: What are existential types in GADTs?
"GADTs naturally support existential types:

Existential Pattern:
data Exists = forall a. Exists a

GADT Style:
data Exists where
  Exists :: a -> Exists

Benefits:
1. Type hiding
2. Abstract data types
3. Heterogeneous collections

Examples:
-- Basic existential with GADT
{-# LANGUAGE GADTs #-}
data Showable where
  Showable :: Show a => a -> Showable

instance Show Showable where
  show (Showable x) = show x

-- Using Showable
showableList :: [Showable]
showableList = [Showable 5, Showable "hello", Showable 3.14]

-- GADT with multiple constraints
data Printable where
  Printable :: (Show a, Read a) => a -> Printable

-- Existential with methods
data Algebra where
  Algebra :: (Num a, Show a) => a -> Algebra

-- Using existential in functions
processShowable :: Showable -> String
processShowable (Showable x) = show x

-- List of different types
data AnyList where
  AnyList :: [a] -> AnyList

-- Type-safe heterogeneous list
data HList where
  HNil :: HList
  HCons :: a -> HList -> HList

-- Using GADT for heterogeneous lists
data HList' a where
  Nil' :: HList' '[]
  Cons' :: a -> HList' as -> HList' (a ': as)

-- Existential with type families
data Expr where
  Expr :: (Typeable a) => a -> Expr

-- Using existential for dynamic typing
fromDynamic :: Typeable a => Expr -> Maybe a
fromDynamic (Expr x) = cast x"
Advanced
60. What are RankNTypes?

RankNTypes allow higher-rank polymorphism.

  • Rank-1: forall a. a -> a
  • Rank-2: (forall a. a -> a) -> Int -> Int
  • Expressiveness: More expressive types
haskell
// Haskell Q60: What are RankNTypes?
"RankNTypes allow higher-rank polymorphism:

Rank-1 Polymorphism:
forall a. a -> a

Rank-2 Polymorphism:
(forall a. a -> a) -> Int -> Int

Benefits:
1. More expressive types
2. Better abstraction
3. Type-safe APIs

Examples:
{-# LANGUAGE RankNTypes #-}

-- Rank-2 type
apply :: (forall a. a -> a) -> Int -> Int
apply f x = f x

-- Using apply
result = apply id 5  -- Works
-- result = apply (+1) 5  -- Doesn't work ((+1) isn't polymorphic)

-- Rank-2 for ST
runST :: (forall s. ST s a) -> a

-- Rank-2 in data types
data Box = Box (forall a. a -> a)

-- Rank-2 in records
data API = API
  { getId :: forall a. a -> a
  , getName :: forall a. Show a => a -> String
  }

-- Higher-rank types in class methods
class Functor f where
  fmap :: (a -> b) -> f a -> f b

-- Rank-N types
-- Rank-3: (forall a. (forall b. a -> b) -> a) -> Int

-- Using higher-rank for type safety
run :: (forall a. Monad m => m a) -> IO a
run m = m

-- Rank-2 with constraints
f :: (forall a. (Show a, Num a) => a -> a) -> Int -> Int
f g x = g x

-- Practical example
type Application = forall m. MonadIO m => m ()"
Advanced
61. What are ScopedTypeVariables?

ScopedTypeVariables bring type variables into scope.

  • Type Annotations: In functions
  • Type Variables: In patterns
  • Better Type Inference: Improved inference
haskell
// Haskell Q61: What are ScopedTypeVariables?
"ScopedTypeVariables bring type variables into scope:

Extension:
{-# LANGUAGE ScopedTypeVariables #-}

Benefits:
1. Type annotations in functions
2. Type variables in patterns
3. Better type inference

Examples:
-- Without scoped variables
f :: [a] -> [a]
f (x:xs) = [x] ++ (g xs)  -- Can't specify type of g

-- With scoped variables
f :: forall a. [a] -> [a]
f (x:xs) = [x] ++ (g xs :: [a])

-- Type signatures in where clauses
process :: forall a. Show a => a -> String
process x = result
  where
    result :: String
    result = show x ++ ":" ++ show x

-- Pattern matching with scoped variables
g :: forall a. (a -> a) -> [a] -> [a]
g f (x:xs) = (f x :: a) : g f xs

-- Nested scopes
h :: forall a b. (a -> b) -> [a] -> [b]
h f xs = map (\x -> f x :: b) xs

-- Scoped variables in data types
data MyType a = MyType a

instance Functor MyType where
  fmap :: forall a b. (a -> b) -> MyType a -> MyType b
  fmap f (MyType x) = MyType (f x :: b)

-- Multiple type variables
i :: forall a b. (a -> b) -> (b -> a) -> a -> b
i f g x = f x

-- Scoped variables in constraints
j :: forall a. (Num a, Show a) => a -> String
j x = show (x + 1)"
Advanced
62. What are MultiParamTypeClasses?

MultiParamTypeClasses allow classes with multiple parameters.

  • Expressiveness: More expressive classes
  • Type Relationships: Better relationships
  • Abstraction: Better abstraction
haskell
// Haskell Q62: What are MultiParamTypeClasses?
"MultiParamTypeClasses allow classes with multiple parameters:

Extension:
{-# LANGUAGE MultiParamTypeClasses #-}

Benefits:
1. More expressive class definitions
2. Type relationships
3. Better abstraction

Examples:
-- Basic multi-param class
class Convert a b where
  convert :: a -> b

instance Convert Int String where
  convert = show

instance Convert String Int where
  convert = read

-- Collection class with two params
class Collection c e where
  empty :: c
  insert :: e -> c -> c
  toList :: c -> [e]

instance Collection [a] a where
  empty = []
  insert x xs = x : xs
  toList = id

-- Key-value relationship
class HasKey k v where
  getValue :: k -> v

-- Multiple params with constraints
class (Eq a, Ord b) => Relate a b where
  compareValues :: a -> a -> b

-- Using multi-param class
class Showable a where
  show :: a -> String

class Readable a where
  read :: String -> a

class Convertible a b where
  convert :: a -> b

-- Multi-param with default methods
class Contains a b where
  contains :: a -> b -> Bool
  contains _ _ = False

-- Type relations
class Map m k v where
  lookup :: k -> m -> Maybe v
  insert :: k -> v -> m -> m"
Advanced
63. What are FlexibleInstances?

FlexibleInstances allow more flexible instance declarations.

  • Complex Instances: More complex instances
  • Type Families: In instances
  • Expressiveness: Better expressiveness
haskell
// Haskell Q63: What are FlexibleInstances?
"FlexibleInstances allow more flexible instance declarations:

Extension:
{-# LANGUAGE FlexibleInstances #-}

Benefits:
1. More complex instances
2. Type families in instances
3. Better expressiveness

Examples:
-- Without FlexibleInstances
instance Eq a => Eq [a] where ...

-- With FlexibleInstances
instance Eq a => Eq (Maybe a) where ...

-- Complex instance
instance (Eq a, Eq b) => Eq (Either a b) where
  (Left x) == (Left y) = x == y
  (Right x) == (Right y) = x == y
  _ == _ = False

-- Instance with type function
instance Eq (a, b) where
  (x1, y1) == (x2, y2) = x1 == x2 && y1 == y2

-- Flexible instance with constraints
instance (Show a, Show b) => Show (a -> b) where
  show _ = "<function>"

-- Instance with newtype
newtype Age = Age Int

instance Eq Age where
  (Age x) == (Age y) = x == y

-- Nested instances
instance (Eq a, Eq b, Eq c) => Eq (a, b, c) where
  (x1, y1, z1) == (x2, y2, z2) = x1 == x2 && y1 == y2 && z1 == z2

-- Instance with type families
type family Key a
type family Value a

instance Eq (Key a) => Eq (Value a) where
  (Value x) == (Value y) = x == y"
Advanced
64. What are TypeOperators?

TypeOperators allow operator symbols in types.

  • Custom Operators: Type-level operators
  • Readability: Readable notation
  • DSL Design: Domain-specific languages
haskell
// Haskell Q64: What are TypeOperators?
"TypeOperators allow operator symbols in types:

Extension:
{-# LANGUAGE TypeOperators #-}

Benefits:
1. Custom type operators
2. Readable type-level notation
3. DSL design

Examples:
-- Custom type operator
type a :+: b = Either a b
type a :*: b = (a, b)

-- Using type operators
type Person = String :*: Int
type Result = String :+: Int

-- Function with type operators
process :: Person -> Result
process (name, age) = if age > 0 then Right age else Left name

-- Type-level list operator
data a ::: b = a ::: b
infixr 5 :::

-- Type operator for maps
type k :-> v = (k, v)

-- Type-level function
type family (a :: *) :+: (b :: *) where
  (a :: *) :+: (b :: *) = Either a b

-- Operator with kind
data (a :*: b) = Product a b

-- Type operator for functions
type a :-> b = a -> b

-- Type operator for constraints
type (a :&: b) = (a, b)

-- Using type operators in classes
class (a :-> b) where
  apply :: a -> b

-- Type operator examples
type Vector a = [a]
type Matrix a = [[a]]
type Point a = (a, a)
type Color = (Int, Int, Int)

-- Type operator for state
type State s a = s -> (a, s)

-- Type operator for effects
type Eff a = IO a"
Advanced
65. What are TypeFamilies and their use cases?

TypeFamilies enable type-level computation.

  • Open Families: Extensible
  • Closed Families: Fixed
  • Associated Families: In classes
haskell
// Haskell Q65: What are TypeFamilies and their use cases?
"TypeFamilies enable type-level computation:

TypeFamily Types:
1. Open families: Extensible
2. Closed families: Fixed
3. Associated families: In classes

Use Cases:
1. Generic programming
2. Type-level computation
3. DSL design

Examples:
-- Open type family
type family Element a where
  type instance Element [a] = a
  type instance Element (Maybe a) = a

-- Closed type family
type family Add a b where
  Add Zero b = b
  Add (Succ a) b = Succ (Add a b)

-- Associated type family
class Container c where
  type Value c :: *
  empty :: c
  insert :: Value c -> c -> c

instance Container [a] where
  type Value [a] = a
  empty = []
  insert x xs = x : xs

-- Type family for collections
type family Collection a where
  Collection [a] = a
  Collection (Maybe a) = a

-- Type-level computation
type family Length xs where
  Length '[] = Zero
  Length (x ': xs) = Succ (Length xs)

-- Type family for constraints
type family IsString a where
  IsString [Char] = True
  IsString a = False

-- Type family with multiple parameters
type family Merge a b where
  Merge (Left a) (Left b) = Left (a,b)
  Merge (Right a) (Right b) = Right (a,b)"
Advanced
66. What are FlexibleContexts?

FlexibleContexts allow more flexible context specifications.

  • Complex Constraints: More complex constraints
  • Type Families: In contexts
  • Expressiveness: Better expressiveness
haskell
// Haskell Q66: What are FlexibleContexts?
"FlexibleContexts allow more flexible context specifications:

Extension:
{-# LANGUAGE FlexibleContexts #-}

Benefits:
1. Complex constraints
2. Type families in contexts
3. Better expressiveness

Examples:
-- Complex context
sort :: (Ord a, Show a) => [a] -> [a]

-- Context with type family
process :: (Elem a ~ Int, Collection a) => a -> Int

-- Constraint with multiple params
f :: (Foo a b, Bar b c) => a -> b -> c

-- Context in data declaration
data Eq a => Set a = Set [a]

-- Context in type synonym
type NumClass a = (Num a, Show a, Ord a)

-- Constraint with type operator
g :: (a ~ b, Show a) => a -> b -> String

-- Using FlexibleContexts with GADTs
data Expr a where
  IntLit :: Int -> Expr Int
  BoolLit :: Bool -> Expr Bool

eval :: (Num a, Ord a) => Expr a -> a

-- Context with newtype
newtype (Ord a) => Sorted a = Sorted [a]

-- Multiple contexts
h :: (Num a, Eq b, Show c) => a -> b -> c -> String

-- Context with functional dependencies
class Collection c e | c -> e where
  empty :: c
  insert :: e -> c -> c

-- Context with associated types
class Collection c where
  type Elem c
  empty :: c
  insert :: Elem c -> c -> c"
Advanced
67. What are DeriveLift and other derivation extensions?

Derivation extensions automatically generate instances.

  • DeriveLift: Template Haskell
  • DeriveFunctor: Functor instances
  • DeriveFoldable: Foldable instances
  • DeriveTraversable: Traversable instances
haskell
// Haskell Q67: What are DeriveLift and other derivation extensions?
"Derivation extensions automatically generate instances:

Common Extensions:
1. DeriveLift: Template Haskell
2. DeriveFunctor: Functor instances
3. DeriveFoldable: Foldable instances
4. DeriveTraversable: Traversable instances
5. DeriveGeneric: Generic instances

Examples:
{-# LANGUAGE DeriveLift #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE DeriveGeneric #-}

-- DeriveFunctor
data Tree a = Leaf a | Node (Tree a) (Tree a)
  deriving (Functor)

-- DeriveFoldable
data List a = Nil | Cons a (List a)
  deriving (Foldable)

-- DeriveTraversable
data Maybe a = Nothing | Just a
  deriving (Traversable)

-- DeriveGeneric
data Person = Person String Int
  deriving (Generic)

-- Using derived instances
sumTree :: Tree Int -> Int
sumTree = sum

-- DeriveLift with Template Haskell
data MyData = MyData Int String
  deriving (Lift)

-- Multiple derivations
data Tree a = Leaf a | Node (Tree a) (Tree a)
  deriving (Show, Eq, Ord, Functor, Foldable, Traversable)

-- Custom deriving
newtype Age = Age Int
  deriving (Num, Eq, Ord, Show)

-- DeriveAnyClass
{-# LANGUAGE DeriveAnyClass #-}
data User = User String Int
  deriving (Show, Eq, Generic, MyClass)

-- Deriving strategies
{-# LANGUAGE DerivingStrategies #-}
data MyType = MyType Int
  deriving newtype (Num)
  deriving stock (Show, Eq)"
Advanced
68. What are StandaloneDeriving?

StandaloneDeriving declares instances separately.

  • GADTs: Derive for GADTs
  • Control Location: Where instances appear
  • Work Around: Restrictions
haskell
// Haskell Q68: What are StandaloneDeriving?
"StandaloneDeriving declares instances separately:

Extension:
{-# LANGUAGE StandaloneDeriving #-}

Benefits:
1. Derive instances for GADTs
2. Control instance location
3. Work around restrictions

Examples:
-- GADT with deriving
data Expr a where
  IntLit :: Int -> Expr Int
  BoolLit :: Bool -> Expr Bool

deriving instance Show (Expr Int)
deriving instance Show (Expr Bool)

-- Standalone deriving for newtype
newtype Age = Age Int
deriving instance Num Age
deriving instance Show Age

-- Complex instance
data MyData a = MyData a
deriving instance (Show a) => Show (MyData a)

-- Standalone with multiple constraints
data Maybe a = Nothing | Just a
deriving instance (Eq a) => Eq (Maybe a)

-- GADT with multiple instances
data List a where
  Nil :: List a
  Cons :: a -> List a -> List a

deriving instance Show a => Show (List a)
deriving instance Eq a => Eq (List a)

-- Standalone for existential
data Showable where
  Showable :: Show a => a -> Showable
deriving instance Show Showable

-- Using standalone with type families
data Family a where
  Family :: a -> Family a
deriving instance (Show a) => Show (Family a)

-- Standalone for recursive types
data Tree a = Leaf a | Node (Tree a) (Tree a)
deriving instance (Show a) => Show (Tree a)"
Advanced
69. What are OverlappingInstances?

OverlappingInstances resolve ambiguous instances.

  • More Specific: Specific instances
  • Resolution Control: Control resolution
  • Flexible Design: Flexible type class design
haskell
// Haskell Q69: What are OverlappingInstances?
"OverlappingInstances resolve ambiguous instances:

Extension:
{-# LANGUAGE OverlappingInstances #-}

Benefits:
1. More specific instances
2. Instance resolution control
3. Flexible type class design

Examples:
-- General instance
instance Show a where
  show x = "Unknown"

-- More specific instance
instance Show Int where
  show x = "Int: " ++ show x

-- Overlapping with constraints
instance (Show a) => Show [a] where
  show xs = "List: " ++ show xs

instance Show [Char] where
  show xs = "String: " ++ xs

-- Using overlapping with type families
class MyClass a where
  myShow :: a -> String

instance MyClass a where
  myShow _ = "Default"

instance MyClass Int where
  myShow x = "Int: " ++ show x

instance MyClass [Int] where
  myShow xs = "Int List: " ++ show xs

-- Overlapping in practice
class Convert a b where
  convert :: a -> b

instance Convert a a where
  convert x = x

instance Convert Int String where
  convert = show

-- Avoiding overlap with INCOHERENT
{-# LANGUAGE IncoherentInstances #-}

-- Best practices
-- Use OverlappingInstances carefully
-- Prefer FlexibleInstances
-- Consider using type families instead"
Advanced
70. What are DefaultSignatures?

DefaultSignatures provide default method implementations.

  • Reduce Boilerplate: Less code
  • Type Class Design: Better design
  • Generic Programming: Generic implementations
haskell
// Haskell Q70: What are DefaultSignatures?
"DefaultSignatures provide default method implementations:

Extension:
{-# LANGUAGE DefaultSignatures #-}

Benefits:
1. Default implementations
2. Reduce boilerplate
3. Type class design

Examples:
-- Basic default signature
class Show a where
  show :: a -> String
  default show :: (Generic a, GShow (Rep a)) => a -> String
  show x = genericShow x

-- Default with constraints
class Eq a where
  (==) :: a -> a -> Bool
  default (==) :: (Generic a, GEq (Rep a)) => a -> a -> Bool
  x == y = genericEq x y

-- Multiple defaults
class ToJSON a where
  toJSON :: a -> String
  default toJSON :: (GToJSON (Rep a)) => a -> String
  toJSON = gToJSON

-- Default with type family
class Serialize a where
  serialize :: a -> String
  default serialize :: (Generic a, GSerialize (Rep a)) => a -> String
  serialize = gSerialize

-- Using default signatures
data Person = Person String Int
  deriving (Generic)

instance Show Person
instance ToJSON Person
instance Serialize Person

-- Default with constraints
class MyClass a where
  myMethod :: a -> String
  default myMethod :: Show a => a -> String
  myMethod x = show x

-- Multiple default methods
class ClassWithDefaults a where
  method1 :: a -> String
  default method1 :: Show a => a -> String
  method1 x = "Default1: " ++ show x
  
  method2 :: a -> Int
  default method2 :: Num a => a -> Int
  method2 x = fromIntegral x"
Advanced
71. What are GeneralizedNewtypeDeriving?

GeneralizedNewtypeDeriving derives instances for newtypes.

  • Instance Reuse: Reuse instances
  • Zero-cost: Abstraction
  • Type Safety: Safe newtypes
haskell
// Haskell Q71: What are GeneralizedNewtypeDeriving?
"GeneralizedNewtypeDeriving derives instances for newtypes:

Extension:
{-# LANGUAGE GeneralizedNewtypeDeriving #-}

Benefits:
1. Instance reuse
2. Zero-cost abstraction
3. Type safety

Examples:
-- Newtype with deriving
newtype Age = Age Int
  deriving (Show, Eq, Ord, Num, Enum, Real, Integral)

-- Using derived instances
age1 = Age 25
age2 = Age 30
age3 = age1 + age2  -- Age 55

-- Newtype with custom class
class Printable a where
  print :: a -> String

instance Printable Int where
  print n = "Int: " ++ show n

newtype MyInt = MyInt Int
  deriving (Printable)

-- Newtype with Functor
newtype Identity a = Identity a
  deriving (Functor)

-- Multiple derivations
newtype Name = Name String
  deriving (Show, Eq, Ord, Read)

-- Deriving with constraints
newtype State s a = State { runState :: s -> (a, s) }
  deriving (Functor, Applicative, Monad)

-- Newtype with Monad
newtype MyMonad a = MyMonad (State Int a)
  deriving (Functor, Applicative, Monad, MonadState Int)

-- Using newtype for type safety
newtype Meters = Meters Double
  deriving (Num, Fractional, Show)

newtype Kilometers = Kilometers Double
  deriving (Num, Fractional, Show)

toMeters :: Kilometers -> Meters
toMeters (Kilometers km) = Meters (km * 1000)

-- Newtype with multiple classes
newtype Email = Email String
  deriving (Show, Eq, Ord, Read, IsString)"
Advanced
72. What are EmptyDataDecls?

EmptyDataDecls allow data types with no constructors.

  • Phantom Types: Type-level programming
  • Uninhabited Types: Types with no values
  • Type Markers: Mark types at compile time
haskell
// Haskell Q72: What are EmptyDataDecls?
"EmptyDataDecls allow data types with no constructors:

Extension:
{-# LANGUAGE EmptyDataDecls #-}

Benefits:
1. Phantom types
2. Type-level programming
3. Uninhabited types

Examples:
-- Empty data declaration
data Void

-- Phantom types
data Meter
data Second

data Quantity a = Quantity Double

toMeters :: Quantity Meter -> Quantity Meter
toMeters x = x

-- Using empty data for safety
data Unvalidated
data Validated

data User a = User { name :: String, age :: Int }

validateUser :: User Unvalidated -> Maybe (User Validated)
validateUser user = 
  if age user > 0 
    then Just (User (name user) (age user))
    else Nothing

-- Empty data for type-level state
data Locked
data Unlocked

data Door s = Door { isOpen :: Bool }

openDoor :: Door Locked -> Door Unlocked
openDoor (Door _) = Door True

-- Empty data for type-level flags
data Debug
data Production

data App a = App

runApp :: App Production -> IO ()
runApp _ = putStrLn "Production mode"

-- Empty data with kind annotation
{-# LANGUAGE DataKinds #-}
data Size = Small | Large

-- Using empty data for type-level computation
data Zero
data Succ n

type family Add a b where
  Add Zero b = b
  Add (Succ a) b = Succ (Add a b)

-- Empty data as type markers
data Public
data Private

data API a = API

-- Using empty data for type safety
data IntList
data CharList

newtype MyList a = MyList [Int]

toIntList :: MyList a -> MyList IntList
toIntList (MyList xs) = MyList xs"
Advanced
73. What are DataKinds?

DataKinds promotes data types to kinds.

  • Type-level: Programming
  • More Precise: Types
  • Dependent-like: Dependent types
haskell
// Haskell Q73: What are DataKinds?
"DataKinds promotes data types to kinds:

Extension:
{-# LANGUAGE DataKinds #-}

Benefits:
1. Type-level programming
2. More precise types
3. Dependent-like types

Examples:
-- Promoting data to kind
data Nat = Zero | Succ Nat

-- Using promoted types
data Vector (n :: Nat) a where
  VNil :: Vector Zero a
  VCons :: a -> Vector n a -> Vector (Succ n) a

-- Type-safe vector operations
vHead :: Vector (Succ n) a -> a
vHead (VCons x _) = x

-- Promoting list to kind
data NList a = NList

type family Length (xs :: [a]) :: Nat where
  Length '[] = Zero
  Length (x ': xs) = Succ (Length xs)

-- Using promoted bool
type family If (b :: Bool) (a :: *) (b :: *) where
  If True a _ = a
  If False _ b = b

-- Promoted tuple
type family Fst (x :: (a,b)) :: a where
  Fst '(a,b) = a

-- Using DataKinds with GADTs
data Expr a where
  IntLit :: Int -> Expr Int
  BoolLit :: Bool -> Expr Bool
  Add :: Expr Int -> Expr Int -> Expr Int

-- Type-safe list
data List' (n :: Nat) a where
  Nil' :: List' Zero a
  Cons' :: a -> List' n a -> List' (Succ n) a

-- Appending type-safe lists
append :: List' n a -> List' m a -> List' (Add n m) a
append Nil' ys = ys
append (Cons' x xs) ys = Cons' x (append xs ys)

-- Promoted Maybe
data Maybe' a = Nothing' | Just' a

type family IsJust (x :: Maybe' a) :: Bool where
  IsJust (Just' _) = True
  IsJust Nothing' = False"
Advanced
74. What are KindSignatures?

KindSignatures explicitly specify kinds.

  • Documentation: Type-level documentation
  • Enforce: Kind correctness
  • Better Errors: Better error messages
haskell
// Haskell Q74: What are KindSignatures?
"KindSignatures explicitly specify kinds:

Extension:
{-# LANGUAGE KindSignatures #-}

Benefits:
1. Type-level documentation
2. Enforce kind correctness
3. Better error messages

Examples:
-- Explicit kind signature
data Maybe (a :: *) = Nothing | Just a

-- Kind signature for type constructor
data Pair (a :: *) (b :: *) = Pair a b

-- Kind signature for higher-kinded type
data Functor (f :: * -> *) = Functor

-- Kind signature for data kind
data Nat = Zero | Succ Nat

data Vector (n :: Nat) (a :: *) where
  VNil :: Vector Zero a
  VCons :: a -> Vector n a -> Vector (Succ n) a

-- Kind signature for type class
class Functor (f :: * -> *) where
  fmap :: (a -> b) -> f a -> f b

-- Kind signature for type family
type family Add (a :: Nat) (b :: Nat) :: Nat where
  Add Zero b = b
  Add (Succ a) b = Succ (Add a b)

-- Kind signature for GADT
data Expr (a :: *) where
  IntLit :: Int -> Expr Int
  BoolLit :: Bool -> Expr Bool

-- Kind signature with constraints
data Valid (a :: *) where
  Valid :: (Show a, Read a) => a -> Valid a

-- Kind signature for type synonym
type State (s :: *) = s

-- Kind signature for data family
data family Vector (a :: *)

-- Kind signature for associated type
class Collection c where
  type Elem (c :: *) :: *"
Advanced
75. What are TypeApplications?

TypeApplications allows explicit type application.

  • Resolve Ambiguity: Clear types
  • Control Instance: Instance selection
  • Type-level: Programming
haskell
// Haskell Q75: What are TypeApplications?
"TypeApplications allows explicit type application:

Extension:
{-# LANGUAGE TypeApplications #-}

Benefits:
1. Resolve ambiguity
2. Control instance selection
3. Use type-level programming

Examples:
-- Basic type application
read :: Read a => String -> a
read @Int "5"  -- 5
read @Bool "True"  -- True

-- Type application with functions
id :: a -> a
id @Int 5  -- 5
id @String "hello"  -- "hello"

-- Type application with polymorphic functions
show @Int 5  -- "5"
show @Bool True  -- "True"

-- Type application with type variables
f :: forall a b. a -> b -> a
f @Int @String 5 "hello"  -- 5

-- Type application in patterns
g :: forall a. Show a => a -> String
g @Int x = show (x + 1)
g @String x = x ++ "!"

-- Type application with partial application
h :: forall a b. a -> b -> a
hInt = h @Int
hInt 5 "hello"  -- 5

-- Type application with constraints
foo :: forall a. (Num a, Show a) => a -> String
foo = show . (+1)
foo @Int 5  -- "6"

-- Type application with data types
maybe :: forall a. a -> Maybe a
maybe @Int 5  -- Just 5

-- Type application with type classes
sum :: Num a => [a] -> a
sum @Int [1,2,3]  -- 6

-- Type application with visible type application
bar :: forall a. a -> (forall b. b -> a) -> a
bar x f = f x
bar @Int 5 @String "hello"  -- 5"
Advanced
76. What are TypeInType?

TypeInType allows types in types.

  • Dependent Types: Type-level programming
  • More Powerful: Types
  • Type-level: Computation
haskell
// Haskell Q76: What are TypeInType?
"TypeInType allows types in types:

Extension:
{-# LANGUAGE TypeInType #-}

Benefits:
1. Dependent types
2. Type-level programming
3. More powerful types

Examples:
-- Type-level numbers
data Nat = Zero | Succ Nat

type family Add (a :: Nat) (b :: Nat) :: Nat where
  Add Zero b = b
  Add (Succ a) b = Succ (Add a b)

-- Dependent vector
data Vector (n :: Nat) a where
  VNil :: Vector Zero a
  VCons :: a -> Vector n a -> Vector (Succ n) a

-- Type-level function
type family Map (f :: a -> b) (xs :: [a]) :: [b] where
  Map f '[] = '[]
  Map f (x ': xs) = f x ': Map f xs

-- Type-level proof
data Equal a b where
  Refl :: Equal a a

-- Type-level singleton
data SNat (n :: Nat) where
  SZero :: SNat Zero
  SSucc :: SNat n -> SNat (Succ n)

-- Using in function
vCons :: a -> Vector n a -> Vector (Succ n) a
vCons x xs = VCons x xs

-- Type-level computation
type family Length (xs :: [a]) :: Nat where
  Length '[] = Zero
  Length (x ': xs) = Succ (Length xs)

-- Type-level append
type family Append (xs :: [a]) (ys :: [a]) :: [a] where
  Append '[] ys = ys
  Append (x ': xs) ys = x ': Append xs ys

-- Type-level reverse
type family Reverse (xs :: [a]) :: [a] where
  Reverse '[] = '[]
  Reverse (x ': xs) = Append (Reverse xs) '[x]"
Advanced
77. What are ConstraintKinds?

ConstraintKinds promotes constraints to kinds.

  • Type-level: Constraints
  • Generic Programming: Generic programming
  • Constraint Composition: Compose constraints
haskell
// Haskell Q77: What are ConstraintKinds?
"ConstraintKinds promotes constraints to kinds:

Extension:
{-# LANGUAGE ConstraintKinds #-}

Benefits:
1. Type-level constraints
2. Generic programming
3. Constraint composition

Examples:
-- Constraint kind
type NumConstraint a = (Num a, Show a)

-- Function with constraint kind
process :: NumConstraint a => a -> String
process x = show (x + 1)

-- Type synonym for constraint
type ToJSON a = Serialize a

-- Constraint in data type
data Dict (c :: Constraint) where
  Dict :: c => Dict c

-- Using Dict
dInt :: Dict (Num Int)
dInt = Dict

-- Constraint composition
type Person a = (Show a, Read a, Eq a)

-- Constraint kind in classes
class (Show a, Read a) => Serializable a

-- Constraint with type families
type family IsString a :: Constraint where
  IsString [Char] = ()
  IsString a = TypeError (Text "Not a string")

-- Using constraints in GADTs
data Showable where
  Showable :: (Show a) => a -> Showable

-- Constraint kind in type families
type family ConstraintFrom a where
  ConstraintFrom Int = NumConstraint Int
  ConstraintFrom String = Show String

-- Constraint kind with type operators
type (c :&: d) a = (c a, d a)

-- Constraint composition example
type EqShow a = (Eq a, Show a)

-- Constraint kind in newtypes
newtype (c a) => Wrapped a = Wrapped a"
Advanced
78. What are PolyKinds?

PolyKinds allows polymorphic kinds.

  • Kind Polymorphism: Generic type-level programming
  • Reusable: Code
  • Generic: Programming
haskell
// Haskell Q78: What are PolyKinds?
"PolyKinds allows polymorphic kinds:

Extension:
{-# LANGUAGE PolyKinds #-}

Benefits:
1. Kind polymorphism
2. Generic type-level programming
3. More reusable code

Examples:
-- Kind polymorphic data
data Proxy (a :: k) = Proxy

-- Kind polymorphic function
proxy :: Proxy a -> Proxy a
proxy x = x

-- Kind polymorphic type family
type family F (a :: k) :: *

-- Kind polymorphic class
class C (a :: k) where
  method :: a -> String

-- Kind polymorphic GADT
data G (a :: k) where
  GInt :: G Int
  GString :: G String
  GMaybe :: G (Maybe a)

-- Using PolyKinds
data Nat = Zero | Succ Nat
data Vector (n :: Nat) (a :: *) = Vector

-- Kind polymorphic singleton
data Sing (a :: k) where
  SInt :: Sing Int
  SString :: Sing String

-- Kind polymorphic type synonym
type Kinded (a :: k) = a

-- Kind polymorphic data family
data family DF (a :: k)

-- Kind polymorphic in class
class Class (a :: k) where
  type ClassType (a :: k) :: *

-- Using PolyKinds for generic programming
type family Rep (a :: k) :: *
type instance Rep Int = IntRep
type instance Rep Bool = BoolRep

-- Kind polymorphic with DataKinds
data MyKind = A | B
data KindedData (a :: MyKind) = KindedData"
Advanced
79. What are DeriveGeneric and Generics?

Generics provide generic programming.

  • Generic Class: type Rep a
  • Generic Functions: Generic programming
  • Reduce Boilerplate: Less code
haskell
// Haskell Q79: What are DeriveGeneric and Generics?
"Generics provide generic programming:

Generic Class:
class Generic a where
  type Rep a :: *
  from :: a -> Rep a
  to :: Rep a -> a

Benefits:
1. Generic functions
2. Reduce boilerplate
3. Type-safe metaprogramming

Examples:
{-# LANGUAGE DeriveGeneric #-}
import GHC.Generics

-- Deriving Generic
data Person = Person String Int
  deriving (Generic)

-- Generic to JSON
class ToJSON a where
  toJSON :: a -> String

instance ToJSON Person where
  toJSON = gToJSON

-- Generic serialization
class Serialize a where
  serialize :: a -> String

instance (Generic a, GSerialize (Rep a)) => Serialize a where
  serialize = gSerialize

-- Generic representation
data User = User
  { userName :: String
  , userAge :: Int
  } deriving (Generic)

-- Generic function for Show
class GShow (f :: * -> *) where
  gshow :: f a -> String

instance (GShow f, GShow g) => GShow (f :*: g) where
  gshow (a :*: b) = gshow a ++ gshow b

instance (Show c) => GShow (K1 i c) where
  gshow (K1 x) = show x

-- Using Generic
instance (Generic a, GShow (Rep a)) => Show a where
  show x = gshow (from x)

-- Generic equality
class GEq (f :: * -> *) where
  geq :: f a -> f a -> Bool

instance (GEq f, GEq g) => GEq (f :*: g) where
  geq (a1 :*: b1) (a2 :*: b2) = geq a1 a2 && geq b1 b2

instance (Eq c) => GEq (K1 i c) where
  geq (K1 x) (K1 y) = x == y

-- Using Generic for default implementations
instance (Generic a, GEq (Rep a)) => Eq a where
  (==) = geq (from x) (from y)"
Advanced
80. What are DeriveAnyClass?

DeriveAnyClass automatically derives instances.

  • Automatic Generation: Instances
  • Reduce Boilerplate: Less code
  • Generic Programming: Generic programming
haskell
// Haskell Q80: What are DeriveAnyClass?
"DeriveAnyClass automatically derives instances:

Extension:
{-# LANGUAGE DeriveAnyClass #-}

Benefits:
1. Automatic instance generation
2. Reduce boilerplate
3. Generic programming

Examples:
-- Define a class with default methods
class MyClass a where
  method :: a -> String
  default method :: (Show a) => a -> String
  method = show

-- Derive instance
data Person = Person String Int
  deriving (MyClass)

-- Using derived instance
person = Person "Alice" 25
print (method person)  -- "Person "Alice" 25"

-- Class with multiple methods
class JSON a where
  toJSON :: a -> String
  fromJSON :: String -> Maybe a
  default toJSON :: (Generic a, GToJSON (Rep a)) => a -> String
  toJSON = gToJSON

-- Derive JSON
data User = User String Int
  deriving (Generic, JSON)

-- Class with constraints
class ShowPretty a where
  pretty :: a -> String
  default pretty :: (Show a) => a -> String
  pretty = show

-- Derive with multiple classes
data MyData = MyData Int String
  deriving (Show, Eq, Ord, MyClass, JSON)

-- Using DeriveAnyClass with GHC.Generics
class Serialize a where
  serialize :: a -> String

instance (Generic a, GSerialize (Rep a)) => Serialize a where
  serialize = gSerialize

-- Derive Serialize
data Person = Person String Int
  deriving (Generic, Serialize)

-- DeriveAnyClass for type classes
class Default a where
  def :: a
  default def :: (Generic a, GDefault (Rep a)) => a
  def = to gdef

-- Derive Default
data Config = Config Bool Int String
  deriving (Generic, Default)"
Advanced
81. What are BangPatterns?

BangPatterns force strict evaluation.

  • Performance: Optimization
  • Space Leak: Prevention
  • Strict Evaluation: Control
haskell
// Haskell Q81: What are BangPatterns?
"BangPatterns force strict evaluation:

Extension:
{-# LANGUAGE BangPatterns #-}

Benefits:
1. Performance optimization
2. Space leak prevention
3. Strict evaluation control

Examples:
-- Strict function
sum' :: [Int] -> Int
sum' xs = go 0 xs
  where
    go !acc [] = acc
    go !acc (x:xs) = go (acc + x) xs

-- Strict pattern matching
strictCase :: Maybe Int -> Int
strictCase !x = case x of
  Nothing -> 0
  Just n -> n

-- Strict in data types
data StrictData = StrictData !Int !String

-- Strict tuple
strictTuple :: (Int, String)
strictTuple = (1, "hello")

-- Strict in where clauses
calculate x y = result
  where
    !result = x + y

-- Strictness in function arguments
f !x !y = x + y

-- Strict list
data StrictList a = SNil | SCons !a !(StrictList a)

-- Pattern matching with bang
head' :: [a] -> a
head' (x:_) = x
head' [] = error "Empty list"

-- Using strictness for performance
foldl' :: (b -> a -> b) -> b -> [a] -> b
foldl' f !acc [] = acc
foldl' f !acc (x:xs) = foldl' f (f acc x) xs

-- Strictness in do notation
main = do
  !x <- getLine
  putStrLn x"
Advanced
82. What are StrictData?

StrictData makes data types strict by default.

  • Performance: Improvement
  • Space Leak: Prevention
  • Predictable: Evaluation
haskell
// Haskell Q82: What are StrictData?
"StrictData makes data types strict by default:

Extension:
{-# LANGUAGE StrictData #-}

Benefits:
1. Performance improvement
2. Space leak prevention
3. Predictable evaluation

Examples:
-- Strict data type
data Person = Person
  { name :: String
  , age :: Int
  }

-- Fields are strict
-- Person { name = undefined, age = 5 } would fail

-- Using with lazy fields
data LazyData = LazyData
  { lazyField :: ~String  -- Lazy
  , strictField :: Int   -- Strict
  }

-- Strict record syntax
data Config = Config
  { configFile :: !FilePath
  , configDebug :: !Bool
  , configLazy :: ~String  -- Explicitly lazy
  }

-- Strict data with multiple constructors
data Maybe a = Nothing | Just !a

-- Strict in pattern matching
caseMaybe :: Maybe Int -> String
caseMaybe (Just !x) = show x
caseMaybe Nothing = "Nothing"

-- Strict newtype
newtype Age = Age !Int

-- Strict in type synonyms
type StrictPair a b = (a, b)  -- Fields strict

-- Using StrictData with BangPatterns
data Foo = Foo !Int !String  -- Both strict

-- Strict data in practice
data Stack a = Empty | Push !a !(Stack a)

-- Lazy fields in strict data
data Mixed = Mixed
  { strict :: !Int
  , lazy :: ~String
  }"
Advanced
83. What are Strict language extension?

Strict makes entire module strict.

  • Performance: Optimization
  • Predictable: Evaluation
  • Space Leak: Prevention
haskell
// Haskell Q83: What are Strict language extension?
"Strict makes entire module strict:

Extension:
{-# LANGUAGE Strict #-}

Benefits:
1. Performance optimization
2. Predictable evaluation
3. Space leak prevention

Examples:
-- Entire module is strict
{-# LANGUAGE Strict #-}

-- All functions are strict by default
add x y = x + y  -- Strict

-- Explicit lazy
lazyAdd x y = x + y
  where
    ~(a,b) = (x,y)

-- Strict data types
data Person = Person String Int  -- Fields strict

-- Strict list
data List a = Nil | Cons a (List a)  -- Fields strict

-- Strict function with lazy pattern
strictFunction :: Int -> Int
strictFunction x = x + 1

-- Lazy pattern matching
lazyMatch (x:xs) = x  -- Lazy

-- Strict in do notation
main = do
  x <- getLine  -- Strict
  putStrLn x

-- Overriding strictness
data LazyData = LazyData ~String  -- Lazy field

-- Strictness in type classes
class MyClass a where
  method :: a -> a  -- Strict by default

-- Combining with other extensions
{-# LANGUAGE Strict, BangPatterns #-}

-- Strictness and patterns
caseValue :: Maybe Int -> String
caseValue (Just !x) = show x
caseValue Nothing = "Nothing"
Advanced
84. What are UnboxedTuples?

UnboxedTuples provide unboxed tuple types.

  • Performance: Optimization
  • Memory Efficiency: Efficient
  • Low-level: Control
haskell
// Haskell Q84: What are UnboxedTuples?
"UnboxedTuples provide unboxed tuple types:

Extension:
{-# LANGUAGE UnboxedTuples #-}

Benefits:
1. Performance optimization
2. Memory efficiency
3. Low-level control

Examples:
-- Unboxed tuple
(# Int, String #)

-- Function returning unboxed tuple
returnTwo :: Int -> (# Int, Int #)
returnTwo x = (# x, x + 1 #)

-- Using unboxed tuple
process (# a, b #) = a + b

-- Unboxed tuple in IO
getTwo :: IO (# Int, Int #)
getTwo = do
  x <- getInt
  y <- getInt
  return (# x, y #)

-- Unboxed tuple with type variables
f :: a -> (# a, a #)
f x = (# x, x #)

-- Unboxed tuple in patterns
g (# x, y #) = x + y

-- Using unboxed tuples for performance
sumPairs :: [(Int, Int)] -> (Int, Int)
sumPairs xs = (# sumX, sumY #)
  where
    (# sumX, sumY #) = foldr add (# 0, 0 #) xs
    add (x,y) (# sx, sy #) = (# sx + x, sy + y #)

-- Unboxed tuple with strictness
h (# !x, !y #) = x + y

-- Unboxed tuple in data types
data MyData = MyData (# Int, String #)

-- Unboxed tuple with type applications
i :: forall a. a -> (# a, a #)
i x = (# x, x #)
j = i @Int 5

-- Unboxed tuple in class
class MyClass a where
  method :: a -> (# a, String #)"
Advanced
85. What are MagicHash and unboxed types?

MagicHash provides access to primitive operations.

  • Low-level: Operations
  • Performance: Optimization
  • FFI: Integration
haskell
// Haskell Q85: What are MagicHash and unboxed types?
"MagicHash provides access to primitive operations:

Extension:
{-# LANGUAGE MagicHash #-}

Benefits:
1. Low-level operations
2. Performance optimization
3. FFI integration

Examples:
-- Unboxed integers
data Int# = Int#

-- Unboxed operations
addInt# :: Int# -> Int# -> Int#
addInt# x y = x +# y

-- Using unboxed types
{-# LANGUAGE MagicHash #-}
import GHC.Prim

-- Primitive operations
toInt :: Int# -> Int
toInt (I# x) = I# x

-- Unboxed character
data Char# = Char#

-- Unboxed float
data Float# = Float#

-- Unboxed operations
floatAdd :: Float# -> Float# -> Float#
floatAdd x y = x +## y

-- Unboxed double
data Double# = Double#

-- Word operations
data Word# = Word#

-- Adding with unboxed types
addWrapper :: Int -> Int -> Int
addWrapper (I# x) (I# y) = I# (x +# y)

-- Unboxed boolean
data Int# = Int#

-- Using unboxed types in FFI
foreign import ccall "add" c_add :: Int# -> Int# -> Int#

-- Unboxed tuple with MagicHash
data MyData = MyData (# Int#, String #)

-- Primitive array
data ByteArray# = ByteArray#

-- Unboxed operations for performance
fastSum :: [Int] -> Int
fastSum xs = I# (go 0# xs)
  where
    go :: Int# -> [Int] -> Int#
    go acc [] = acc
    go acc (I# x:xs) = go (acc +# x) xs"
Advanced
86. What are OverloadedStrings?

OverloadedStrings allows string literals for any type.

  • String-like: Types
  • Text Optimization: Efficient text
  • DSL Design: Domain-specific languages
haskell
// Haskell Q86: What are OverloadedStrings?
"OverloadedStrings allows string literals for any type:

Extension:
{-# LANGUAGE OverloadedStrings #-}

Benefits:
1. String-like types
2. Text optimization
3. DSL design

Examples:
-- Using with Text
import Data.Text (Text)
import qualified Data.Text as T

text :: Text
text = "hello"  -- Overloaded string

-- Using with ByteString
import Data.ByteString (ByteString)

bs :: ByteString
bs = "world"

-- Using with custom type
data MyString = MyString String

instance IsString MyString where
  fromString = MyString

myStr :: MyString
myStr = "hello world"

-- Overloaded strings in JSON
import Data.Aeson
data Person = Person { name :: String, age :: Int }

instance FromJSON Person where
  parseJSON = withObject "Person" $ \v -> Person
    <$> v .: "name"
    <*> v .: "age"

-- Using with SQL
data SQL = SQL String

instance IsString SQL where
  fromString = SQL

query :: SQL
query = "SELECT * FROM users"

-- Overloaded strings in HTML
data HTML = HTML String

instance IsString HTML where
  fromString = HTML

html :: HTML
html = "<div>Hello</div>"

-- Using with URI
data URI = URI String

instance IsString URI where
  fromString = URI

uri :: URI
uri = "http://example.com"

-- Overloaded strings with type annotation
text2 :: Text
text2 = "annotated"

-- Using with template Haskell
{-# LANGUAGE TemplateHaskell #-}
import Language.Haskell.TH
string = [q|"hello"|]"
Advanced
87. What are OverloadedLists?

OverloadedLists allows list literals for any type.

  • List-like: Types
  • Custom Collections: Collections
  • DSL Design: Domain-specific languages
haskell
// Haskell Q87: What are OverloadedLists?
"OverloadedLists allows list literals for any type:

Extension:
{-# LANGUAGE OverloadedLists #-}

Benefits:
1. List-like types
2. Custom collections
3. DSL design

Examples:
-- Using with Vector
import Data.Vector (Vector, fromList)

vec :: Vector Int
vec = [1,2,3,4,5]  -- Overloaded list

-- Using with Set
import Data.Set (Set, fromList)

set :: Set Int
set = [1,2,3,4,5]

-- Using with custom type
data MyList a = MyList [a]

instance IsList (MyList a) where
  type Item (MyList a) = a
  fromList = MyList
  toList (MyList xs) = xs

myList :: MyList Int
myList = [1,2,3]

-- Using with Map
import Data.Map (Map, fromList)

map :: Map Int String
map = [(1,"one"), (2,"two")]

-- Using with Text
import Data.Text (Text, pack)

text :: Text
text = ["hello", "world"]  -- Not supported by default

-- Using with HashMap
import Data.HashMap.Strict (HashMap, fromList)

hashmap :: HashMap Int String
hashmap = [(1,"one"), (2,"two")]

-- Using with custom monoid
newtype Count = Count Int

instance IsList Count where
  type Item Count = Int
  fromList xs = Count (sum xs)
  toList (Count x) = [x]

count :: Count
count = [1,2,3,4,5]  -- Count 15

-- Using with Seq
import Data.Sequence (Seq, fromList)

seq :: Seq Int
seq = [1,2,3]

-- Overloaded lists in pattern matching
match (x:xs) = x + sum xs"
Advanced
88. What are ViewPatterns?

ViewPatterns allows pattern matching with functions.

  • Cleaner Code: More readable
  • Expressiveness: More expressive patterns
  • Computation: Pattern matching with computation
haskell
// Haskell Q88: What are ViewPatterns?
"ViewPatterns allows pattern matching with functions:

Extension:
{-# LANGUAGE ViewPatterns #-}

Benefits:
1. Pattern matching with computation
2. Cleaner code
3. More expressive patterns

Examples:
-- Basic view pattern
f (length -> 0) = "Empty"
f (length -> 1) = "Single"
f (length -> n) = show n

-- Using view patterns with Maybe
g (Just . read -> Just n) = n + 1
g _ = 0

-- View pattern with multiple variables
h (x -> a, y -> b) = a + b

-- Complex view pattern
parse (words -> ["add", x, y]) = read x + read y
parse (words -> ["mul", x, y]) = read x * read y
parse _ = 0

-- View pattern with records
data Person = Person { name :: String, age :: Int }

isAdult (age -> a) = a >= 18

-- Nested view patterns
process (reverse -> (head -> x)) = x

-- View pattern with where
isEven (\n -> n `mod` 2 == 0 -> True) = "Even"
isEven _ = "Odd"

-- View pattern with list comprehension
evens (filter even -> xs) = sum xs

-- View pattern in case expression
case "123" of
  (read -> n) -> n + 1

-- View pattern with complex function
toUpperAll (map toUpper -> s) = s

-- View pattern with type class
showIt (show -> s) = s ++ "!"
Advanced
89. What are PatternSynonyms?

PatternSynonyms allow creating custom patterns.

  • Custom Patterns: Create patterns
  • Abstract Data Types: Hide implementation
  • Bidirectional: Bidirectional patterns
haskell
// Haskell Q89: What are PatternSynonyms?
"PatternSynonyms allow creating custom patterns:

Extension:
{-# LANGUAGE PatternSynonyms #-}

Benefits:
1. Custom pattern matching
2. Abstract data types
3. Bidirectional patterns

Examples:
-- Basic pattern synonym
pattern Cons x xs = x : xs

-- Using pattern synonym
head' (Cons x _) = x

-- Bidirectional pattern
pattern Nil = []

-- Pattern with constraints
pattern Even n <- (n `mod` 2 == 0 -> True)
  where Even n = n * 2

-- Using pattern
isEven (Even _) = True
isEven _ = False

-- Pattern with multiple arguments
pattern Pair a b = (a, b)

-- Pattern with type
pattern Str s = (s :: String)

-- Pattern with GADT
data Expr a where
  IntLit :: Int -> Expr Int
  BoolLit :: Bool -> Expr Bool

pattern Lit n = IntLit n

-- Pattern with record
data Person = Person { name :: String, age :: Int }
pattern P n a = Person { name = n, age = a }

-- Pattern with view pattern
pattern RightString s <- Right (s :: String)

-- Pattern with existential
data Showable = forall a. Show a => Showable a
pattern Showable' x = Showable x

-- Using pattern synonyms
f (P n a) = n ++ show a

-- Pattern with list
pattern Head x = x : _

-- Pattern with tuple
pattern Triple a b c = (a, (b, c))

-- Pattern with Maybe
pattern Just' x = Just x
pattern Nothing' = Nothing"
Advanced
90. What are RebindableSyntax?

RebindableSyntax allows rebinding built-in syntax.

  • Custom DSLs: Domain-specific languages
  • Alternative Interpretations: Different meanings
  • Control: Over syntactic sugar
haskell
// Haskell Q90: What are RebindableSyntax?
"RebindableSyntax allows rebinding built-in syntax:

Extension:
{-# LANGUAGE RebindableSyntax #-}

Benefits:
1. Custom DSLs
2. Alternative interpretations
3. Control over syntactic sugar

Examples:
-- Rebind if-then-else
myIf :: Bool -> a -> a -> a
myIf True x _ = x
myIf False _ y = y

-- Using rebindable syntax
if True then 5 else 6  -- Uses myIf

-- Rebind do notation
myBind :: Maybe a -> (a -> Maybe b) -> Maybe b
myBind (Just x) f = f x
myBind Nothing _ = Nothing

myReturn :: a -> Maybe a
myReturn = Just

-- Using do with myBind
do
  x <- Just 5
  return (x + 1)

-- Rebind list comprehension
myMap :: (a -> b) -> [a] -> [b]
myMap = map

myFilter :: (a -> Bool) -> [a] -> [a]
myFilter = filter

-- Using list comprehension
[x | x <- [1..10], even x]

-- Rebind arithmetic
myAdd :: Int -> Int -> Int
myAdd x y = x + y

-- Using arithmetic
5 + 6  -- Uses myAdd

-- Rebind fromInteger
myFromInteger :: Integer -> Int
myFromInteger = fromInteger

-- Using numeric literals
5  -- Uses myFromInteger

-- Rebind fail
myFail :: String -> Maybe a
myFail _ = Nothing

-- Using fail in do
do
  x <- Just 5
  fail "error"

-- Rebind mdo
{-# LANGUAGE RebindableSyntax, RecursiveDo #-}
myMdo :: m a -> m a
myMdo = id"
Advanced
91. What are DoAndIfThenElse?

DoAndIfThenElse enables custom do and if syntax.

  • Custom DSLs: Domain-specific languages
  • Alternative Monads: Different monads
  • More Control: Over syntax
haskell
// Haskell Q91: What are DoAndIfThenElse?
"DoAndIfThenElse enables custom do and if syntax:

Extension:
{-# LANGUAGE DoAndIfThenElse #-}

Benefits:
1. Custom DSLs
2. Alternative monads
3. More control

Examples:
-- Custom if
myIf :: Bool -> a -> a -> a
myIf True x _ = x
myIf False _ y = y

-- Using if
if 5 > 3 then "Yes" else "No"

-- Custom do
data MyMonad a = MyMonad a

myBind :: MyMonad a -> (a -> MyMonad b) -> MyMonad b
myBind (MyMonad x) f = f x

myReturn :: a -> MyMonad a
myReturn = MyMonad

-- Using do
do
  x <- MyMonad 5
  return (x + 1)

-- Custom fail
myFail :: String -> MyMonad a
myFail _ = MyMonad undefined

-- Using fail in do
do
  x <- MyMonad 5
  fail "error"
  return x

-- Custom guard
myGuard :: Bool -> MyMonad ()
myGuard True = MyMonad ()
myGuard False = fail "guard"

-- Using guard
do
  guard (5 > 3)
  return True

-- Custom mdo
{-# LANGUAGE RecursiveDo #-}
myMdo :: m a -> m a
myMdo = id

-- Using mdo
mdo
  x <- return 5
  return x

-- Custom arrow
myArr :: (a -> b) -> a -> b
myArr f x = f x

-- Using arrow syntax
{-# LANGUAGE Arrows #-}
proc x -> returnA -< x + 1"
Advanced
92. What are TemplateHaskell and QuasiQuotes?

TemplateHaskell enables compile-time metaprogramming.

  • Code Generation: Generate code
  • Compile-time: Computation
  • DSL Embedding: Domain-specific languages
haskell
// Haskell Q92: What are TemplateHaskell and QuasiQuotes?
"TemplateHaskell enables compile-time metaprogramming:

Extensions:
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE QuasiQuotes #-}

Benefits:
1. Code generation
2. Compile-time computation
3. DSL embedding

Examples:
-- Template Haskell basics
import Language.Haskell.TH

-- Generating function
double :: Q [Dec]
double = do
  let name = mkName "double"
  let expr = [| \x -> x * 2 |]
  return [FunD name [Clause [VarP (mkName "x")] (NormalB expr) []]]

$(double)

-- Using generated function
result = double 5  -- 10

-- QuasiQuotes
data SQL = SQL String

sql :: QuasiQuoter
sql = QuasiQuoter
  { quoteExp = \s -> [| SQL s |]
  , quotePat = undefined
  , quoteType = undefined
  , quoteDec = undefined
  }

-- Using quasi quote
query = [sql|SELECT * FROM users|]

-- Template Haskell for deriving instances
deriveJSON :: Name -> Q [Dec]
deriveJSON name = do
  -- Implementation
  return []

$(deriveJSON ''Person)

-- QuasiQuotes for regular expressions
import Text.Regex.PCRE.Heavy
regex :: QuasiQuoter
regex = ...

-- Using regex
matches = [re|^[a-z]+$|] "hello"

-- Template Haskell for debugging
$(print "Generating code at compile time")

-- QuasiQuotes for HTML
html :: QuasiQuoter
html = ...

-- Using HTML
page = [html|<div>Hello</div>|]

-- Template Haskell for performance
$(do
  putStrLn "Generating optimized code"
  return [])

-- QuasiQuotes for JSON
json :: QuasiQuoter
json = ...

-- Using JSON
data = [json|{"name": "Alice", "age": 25}|]
Advanced
93. What are QuasiQuotes for DSLs?

QuasiQuotes enable domain-specific languages.

  • Custom Syntax: Domain-specific syntax
  • Type-safe: Embedding
  • Compile-time: Validation
haskell
// Haskell Q93: What are QuasiQuotes for DSLs?
"QuasiQuotes enable domain-specific languages:

Benefits:
1. Custom syntax
2. Type-safe embedding
3. Compile-time validation

Examples:
-- SQL QuasiQuoter
{-# LANGUAGE QuasiQuotes #-}

sql :: QuasiQuoter
sql = QuasiQuoter
  { quoteExp = \s -> do
      -- Validate SQL syntax
      -- Generate typed expression
      return [| SQL s |]
  , quotePat = undefined
  , quoteType = undefined
  , quoteDec = undefined
  }

-- Using SQL
query :: SQL
query = [sql|SELECT name, age FROM users WHERE age > 18|]

-- Regex QuasiQuoter
regex :: QuasiQuoter
regex = QuasiQuoter
  { quoteExp = \s -> do
      -- Compile regex at compile time
      return [| compileRegex s |]
  , quotePat = undefined
  , quoteType = undefined
  , quoteDec = undefined
  }

-- Using regex
isEmail = [re|^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$|]

-- HTML QuasiQuoter
html :: QuasiQuoter
html = QuasiQuoter
  { quoteExp = \s -> do
      -- Parse HTML at compile time
      return [| HTML s |]
  , quotePat = undefined
  , quoteType = undefined
  , quoteDec = undefined
  }

-- Using HTML
page :: HTML
page = [html|<div class="container"><h1>Hello</h1></div>|]

-- JSON QuasiQuoter
json :: QuasiQuoter
json = QuasiQuoter
  { quoteExp = \s -> do
      -- Parse JSON at compile time
      return [| parseJSON s |]
  , quotePat = undefined
  , quoteType = undefined
  , quoteDec = undefined
  }

-- Using JSON
person :: Person
person = [json|{"name":"Alice","age":25}|]

-- XML QuasiQuoter
xml :: QuasiQuoter
xml = ...

-- YAML QuasiQuoter
yaml :: QuasiQuoter
yaml = ...

-- Custom DSL for arithmetic
arith :: QuasiQuoter
arith = ...
Advanced
94. What are TypeSynonymInstances?

TypeSynonymInstances allows instances for type synonyms.

  • Flexible: Instance declarations
  • Type-level: Abstraction
  • Type Synonyms: In instances
haskell
// Haskell Q94: What are TypeSynonymInstances?
"TypeSynonymInstances allows instances for type synonyms:

Extension:
{-# LANGUAGE TypeSynonymInstances #-}

Benefits:
1. Type synonyms in instances
2. Flexible instance declarations
3. Type-level abstraction

Examples:
-- Type synonym
type StringList = [String]

-- Instance with type synonym
instance Show StringList where
  show xs = "StringList: " ++ show xs

-- Complex type synonym
type Map k v = [(k, v)]

instance Show (Map String Int) where
  show m = "Map: " ++ show m

-- Type synonym with constraints
type NumList a = [a]

instance Num a => Show (NumList a) where
  show xs = "NumList: " ++ show xs

-- Type synonym in class
type JSON a = a

instance Show (JSON Person) where
  show p = "JSON: " ++ show p

-- Type synonym with multiple parameters
type Pair a b = (a, b)

instance (Show a, Show b) => Show (Pair a b) where
  show (x,y) = "Pair: " ++ show x ++ " " ++ show y

-- Type synonym in newtype
type Age = Int
newtype Person = Person (String, Age)

-- Using type synonym in instances
instance Show Age where
  show (Age x) = show x

-- Type synonym with higher-kinded types
type Functor' f a = f a

instance Functor (Functor' Maybe) where
  fmap f (Just x) = Just (f x)
  fmap f Nothing = Nothing

-- Type synonym in context
type NumShow a = (Num a, Show a)

instance NumShow Int where
  -- Implementation

-- Type synonym in data declaration
data Container a = Container (Vector a)
type Vector a = [a]
Advanced
95. What are UndecidableInstances?

UndecidableInstances allows complex instance resolution.

  • Advanced: Type-level programming
  • Recursive Instances: Recursion
  • Type-level: Computation
haskell
// Haskell Q95: What are UndecidableInstances?
"UndecidableInstances allows complex instance resolution:

Extension:
{-# LANGUAGE UndecidableInstances #-}

Benefits:
1. Advanced type-level programming
2. Recursive instances
3. Type-level computation

Examples:
-- Recursive instance
instance (Num a, Show a) => Show [a] where
  show xs = "List: " ++ show xs

-- Nested instances
instance (Show a, Show b) => Show (Either a b) where
  show (Left x) = "Left: " ++ show x
  show (Right x) = "Right: " ++ show x

-- Instance with type families
type family Elem a where
  Elem [a] = a

instance (Show (Elem a)) => Show a where
  show x = "Element: " ++ show (x :: Elem a)

-- Recursive constraints
class MyClass a where
  method :: a -> String

instance (MyClass a, MyClass b) => MyClass (Either a b) where
  method (Left x) = "Left: " ++ method x
  method (Right x) = "Right: " ++ method x

-- Complex instance resolution
class Convert a b where
  convert :: a -> b

instance (Convert a b, Convert b c) => Convert a c where
  convert = convert . convert

-- Instance with functional dependencies
class Collection c a | c -> a

instance Collection [a] a

instance (Collection c a) => Collection (Maybe c) a

-- Instance with overlapping
instance {-# OVERLAPPABLE #-} Show a => Show [a]
instance {-# OVERLAPPING #-} Show [Int]

-- Instance with incoherent
instance {-# INCOHERENT #-} Num a => Show a

-- Using undecidable instances for type-level lists
instance (Show a, Show (List a)) => Show (List a) where
  show (Cons x xs) = show x ++ ", " ++ show xs
  show Nil = ""
Advanced
96. What are FlexibleContexts and UndecidableInstances?

Both enable advanced type-level programming.

  • FlexibleContexts: Complex contexts
  • UndecidableInstances: Recursive instances
  • Type-level: Computation
haskell
// Haskell Q96: What are FlexibleContexts and UndecidableInstances?
"Both enable advanced type-level programming:

FlexibleContexts:
- Allows complex context specifications
- Better expressiveness
- Type safety

UndecidableInstances:
- Allows recursive instances
- Type-level computation
- Complex instance resolution

Examples:
-- FlexibleContexts
class MyClass a where
  method :: a -> String

instance (MyClass a, Show a) => MyClass [a] where
  method xs = "List: " ++ show xs

-- UndecidableInstances
instance (MyClass a, MyClass b) => MyClass (a, b) where
  method (x,y) = method x ++ ", " ++ method y

-- Combining both
class Convert a b where
  convert :: a -> b

instance (Convert a b, Convert b c) => Convert a c where
  convert = convert . convert

-- Type-level computation
type family Add a b where
  Add Zero b = b
  Add (Succ a) b = Succ (Add a b)

-- Instance with type family
instance (Num a, Num (Add a b)) => Num (Add a b) where
  -- Implementation

-- Recursive constraints
class Collection c a | c -> a

instance (Collection c a) => Collection (Maybe c) a

-- Complex context
f :: (Show a, Eq a, Num a, Ord a) => a -> String
f x = show (x + 1)

-- Flexible context with type families
process :: (Elem a ~ Int, Show a) => a -> String

-- Undecidable instances for type-level lists
instance (Show a, Show (List a)) => Show (List a)

-- Instance with multiple constraints
instance (Show a, Show b, Show c) => Show (a, b, c)
Advanced
97. What are RankNTypes and ScopedTypeVariables together?

Combining these extensions enables advanced polymorphism.

  • Higher-rank: Polymorphism
  • Scoped Type Variables: Type variables in scope
  • Precise Type: Control
haskell


Benefits:
1. Higher-rank polymorphism
2. Scoped type variables
3. Precise type control

Examples:
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}

-- Rank-2 with scoped variables
f :: forall a. (forall b. b -> b) -> a -> a
f g x = g x

-- Higher-rank in data types
data Box = Box (forall a. a -> a)

-- Scoped variables in rank-2
runST :: forall a. (forall s. ST s a) -> a

-- Rank-2 with constraints
apply :: forall a. (forall b. Show b => b -> String) -> a -> String
apply f x = f x

-- Scoped variables in higher-rank
g :: forall a. (forall b. (Num b) => b -> b) -> a -> a
g f x = f x

-- Rank-N in class methods
class Functor f where
  fmap :: (a -> b) -> f a -> f b

-- Scoped variables with constraints
h :: forall a b. (Show a, Show b) => (forall c. Show c => c -> String) -> a -> b -> String
h f x y = f x ++ " " ++ f y

-- Higher-rank in records
data API = API
  { getId :: forall a. a -> a
  , getName :: forall a. Show a => a -> String
  }

-- Scoped variables in pattern matching
process :: forall a. Show a => a -> String
process x = show (x :: a)

-- Rank-2 with type applications
run :: forall a. (forall s. ST s a) -> a
run st = runST st

-- Combining with other extensions
{-# LANGUAGE RankNTypes, ScopedTypeVariables, TypeApplications #-}

-- Using type applications with rank-N
foo :: forall a. (forall b. b -> a) -> a
foo f = f @Int 5"
Advanced
98. What are the best practices for Haskell development?

Best practices for effective Haskell development.

  • Code Organization: Modules and structure
  • Type Safety: Newtypes, ADTs
  • Performance: Strictness, profiling
  • Testing: QuickCheck, unit tests
haskell
// Haskell Q98: What are the best practices for Haskell development?
"Best practices for Haskell development:

1. Code Organization:
   - Use modules effectively
   - Export minimal API
   - Separate concerns
   - Use type synonyms for clarity

2. Type Safety:
   - Use newtypes for safety
   - Leverage algebraic data types
   - Use phantom types
   - Prefer total functions

3. Performance:
   - Use strict annotations
   - Profile code
   - Use appropriate data structures
   - Leverage laziness appropriately

4. Testing:
   - Write property tests
   - Use QuickCheck
   - Write unit tests
   - Benchmark code

5. Documentation:
   - Write Haddock comments
   - Document types
   - Include examples
   - Explain invariants

6. Build Tools:
   - Use Stack or Cabal
   - Manage dependencies
   - Use GHC warnings
   - Enable language extensions judiciously

7. Code Style:
   - Follow Haskell style guide
   - Use consistent naming
   - Write readable code
   - Comment complex code

8. Error Handling:
   - Use appropriate monads
   - Handle errors gracefully
   - Use Either for errors
   - Leverage exceptions sparingly

Examples:
-- Good practice
newtype UserId = UserId Int
  deriving (Show, Eq, Ord)

-- Type safe functions
createUser :: UserId -> UserName -> UserEmail -> User

-- Documentation
-- | Creates a new user with given ID, name, and email
-- >>> createUser (UserId 1) (UserName "Alice") (UserEmail "alice@example.com")

-- Property tests
prop_inverse :: [Int] -> Bool
prop_inverse xs = reverse (reverse xs) == xs

-- Performance optimization
sum' :: [Int] -> Int
sum' = foldl' (+) 0"
Advanced
99. What are common Haskell interview pitfalls?

Common pitfalls to avoid in Haskell interviews.

  • Laziness Issues: Space leaks
  • Type Errors: Ambiguous types
  • Monad Confusion: IO vs pure
  • Performance: Inefficient data structures
haskell


1. Laziness Issues:
   - Space leaks from thunks
   - Unexpected memory usage
   - Use strictness annotations

2. Type Errors:
   - Ambiguous types
   - Missing type signatures
   - Use explicit type annotations

3. Monad Confusion:
   - Using IO when pure is possible
   - Monad transformer complexity
   - Start with simple monads

4. Performance:
   - Inefficient data structures
   - Unnecessary allocations
   - Use appropriate data types

5. Pattern Matching:
   - Non-exhaustive patterns
   - Partial functions
   - Use total functions

6. Type Classes:
   - Ambiguous instances
   - Overlapping instances
   - Use safe instance declarations

7. Error Handling:
   - Ignoring errors
   - Partial functions
   - Use total error handling

8. Module Management:
   - Orphan instances
   - Circular dependencies
   - Clean module structure

Examples:
-- Bad: Partial function
head' [] = error "Empty"

-- Good: Total function
headMaybe :: [a] -> Maybe a
headMaybe (x:_) = Just x
headMaybe [] = Nothing

-- Bad: Space leak
badSum = foldl (+) 0 [1..1000000]

-- Good: Strict fold
goodSum = foldl' (+) 0 [1..1000000]

-- Bad: Ambiguous type
read "5"

-- Good: Explicit type
read "5" :: Int

-- Bad: IO when pure
readFileAndProcess path = do
  content <- readFile path
  return (process content)

-- Good: Separate IO and pure
processContent = process content
  where content = readFile path
Advanced
100. What are the advanced concepts in Haskell?

Advanced Haskell concepts enable sophisticated type-level programming and effect management.

  • Type-Level Programming: DataKinds, Type Families, GADTs
  • Effect Systems: Monad Transformers, Algebraic Effects
  • Generic Programming: DeriveGeneric, Type-safe Serialization
  • Dependent Types: Singletons, Type-level Proofs
haskell


1. Type-Level Programming:
   - DataKinds for type-level values
   - Type families for computation
   - GADTs for precise types

2. Effect Systems:
   - Monad transformers
   - Effect libraries (freer-simple, effectful)
   - Algebraic effects

3. Generic Programming:
   - DeriveGeneric
   - Generic representations
   - Type-safe serialization

4. Dependent Types:
   - Singletons
   - Type-level proofs
   - Smart constructors

5. Concurrency:
   - Async and par
   - Software transactional memory
   - Distributed Haskell

6. Performance Optimization:
   - Unboxed types
   - Stream fusion
   - Rewrite rules

7. Metaprogramming:
   - Template Haskell
   - QuasiQuotes
   - Type providers

8. Advanced Patterns:
   - Free monads
   - Coeffects
   - Type-level state machines

Examples:
-- Type-level vector
data Vector (n :: Nat) a where
  VNil :: Vector Zero a
  VCons :: a -> Vector n a -> Vector (Succ n) a

-- Type-level safe append
append :: Vector n a -> Vector m a -> Vector (Add n m) a
append VNil ys = ys
append (VCons x xs) ys = VCons x (append xs ys)

-- Generic programming
instance (Generic a, GToJSON (Rep a)) => ToJSON a where
  toJSON = gToJSON

-- Effect system
type App = Eff
  '[ Reader Config
   , State AppState
   , Log String
   , IOE ]

-- Concurrent programming
parallelMap :: (a -> b) -> [a] -> [b]
parallelMap f = runPar $ do
  results <- parMap f xs
  return results

-- Template Haskell for optimizations
$(deriveFunctor ''MyType)
$(deriveFoldable ''MyType)
$(deriveTraversable ''MyType)