-
Notifications
You must be signed in to change notification settings - Fork 4
Haskell & Plutus Language Extensions
- 1. GADTs
- 2. TypeFamilies
- 3. MultiParamTypeClasses
- 4. FunctionalDependencies
- 5. DataKinds
- 6. ViewPatterns
- 7. PatternSynonyms
- 8. OverloadedStrings
- 9. TemplateHaskell
- 10. RecordWildCards
- 11. KindSignatures
- 12. ScopedTypeVariables
- 13. RankNTypes
- 14. OverloadedLists
- 15. DeriveGeneric
- 16. StandaloneDeriving
- 17. LambdaCase
- 18. QuasiQuotes
- 19. RebindableSyntax
- 20. NamedFieldPuns
- 21. NoImplicitPrelude
- 22. TemplateHaskell
- 23. DeriveAnyClass
- 24. DeriveGeneric
- 25. TypeApplications
- 26. Summary Table Cheat Sheat
Category: Type System
Scope: Haskell
How to Enable: {-# LANGUAGE GADTs #-}
When to Use:
When you need more precise typing in data constructors (e.g., embedded DSLs).
Usage Example:
data Expr a where
Lit :: Int -> Expr Int
Add :: Expr Int -> Expr Int -> Expr IntCategory: Type System
Scope: Haskell
How to Enable: {-# LANGUAGE TypeFamilies #-}
When to Use:
When you need type-level functions associated with type classes.
Usage Example:
type family F a :: *
type instance F Int = BoolCategory: Type Classes
Scope: Haskell
How to Enable: {-# LANGUAGE MultiParamTypeClasses #-}
When to Use:
When a type class logically relates more than one type.
Usage Example:
class Convertible a b where
convert :: a -> bCategory: Type Classes
Scope: Haskell
How to Enable: {-# LANGUAGE FunctionalDependencies #-}
When to Use:
To help GHC infer types in multi-parameter type classes.
Usage Example:
class Convertible a b | a -> b where
convert :: a -> bCategory: Type-Level Programming
Scope: Haskell
How to Enable: {-# LANGUAGE DataKinds #-}
When to Use:
For type-level programming with promoted data constructors.
Usage Example:
data Nat = Zero | Succ Nat
data Vec (n :: Nat) a = ...Category: Pattern Matching
Scope: Haskell
How to Enable: {-# LANGUAGE ViewPatterns #-}
When to Use:
When pattern matching requires function application results.
Usage Example:
f (length -> 0) = "Empty"
f _ = "Not Empty"Category: Pattern Matching
Scope: Haskell
How to Enable: {-# LANGUAGE PatternSynonyms #-}
When to Use:
To simplify or abstract complex patterns.
Usage Example:
pattern Zero <- 0
pattern Succ n <- (n + 1)Category: Literals
Scope: Haskell
How to Enable: {-# LANGUAGE OverloadedStrings #-}
When to Use:
When using string literals as Text, ByteString, etc.
Usage Example:
myText :: Text
myText = "hello"Category: Meta-programming
Scope: Haskell
How to Enable: {-# LANGUAGE TemplateHaskell #-}
When to Use:
For compile-time code generation (e.g., JSON derivation).
Usage Example:
$(deriveJSON defaultOptions ''MyType)Category: Records
Scope: Haskell
How to Enable: {-# LANGUAGE RecordWildCards #-}
When to Use:
To reduce boilerplate in record pattern matching.
Usage Example:
printPerson Person{..} = putStrLn nameCategory: Type-Level Programming
Scope: Haskell
How to Enable: {-# LANGUAGE KindSignatures #-}
When to Use:
To explicitly specify the kind of a type parameter.
Usage Example:
data Proxy (a :: *) = ProxyCategory: Type System
Scope: Haskell
How to Enable: {-# LANGUAGE ScopedTypeVariables #-}
When to Use:
When you need to reuse type variables across scopes.
Usage Example:
f :: forall a. a -> a
f x = let g :: a -> a
g y = y in g xCategory: Type System
Scope: Haskell
How to Enable: {-# LANGUAGE RankNTypes #-}
When to Use:
When you need higher-rank polymorphism in function types.
Usage Example:
f :: (forall a. a -> a) -> IntCategory: Literals
Scope: Haskell
How to Enable: {-# LANGUAGE OverloadedLists #-}
When to Use:
To allow list literals to work with any IsList type.
Usage Example:
myVec :: Vector Int
myVec = [1, 2, 3]Category: Deriving
Scope: Haskell
How to Enable: {-# LANGUAGE DeriveGeneric #-}
When to Use:
To derive Generic instance for use with libraries like Aeson.
Usage Example:
data Person = Person String Int deriving (Generic)Category: Deriving
Scope: Haskell
How to Enable: {-# LANGUAGE StandaloneDeriving #-}
When to Use:
To derive instances for types declared elsewhere or abstract.
Usage Example:
deriving instance Show MyTypeCategory: Pattern Matching
Scope: Haskell
How to Enable: {-# LANGUAGE LambdaCase #-}
When to Use:
For concise anonymous functions with pattern matching.
Usage Example:
f = \case Just x -> x; Nothing -> 0Category: Meta-programming
Scope: Haskell
How to Enable: {-# LANGUAGE QuasiQuotes #-}
When to Use:
To embed DSLs or formatted literals inside Haskell code.
Usage Example:
[sql|SELECT * FROM users|]Category: Syntax
Scope: Haskell
How to Enable: {-# LANGUAGE RebindableSyntax #-}
When to Use:
To override built-in Haskell syntax like if, do, etc.
Usage Example:
ifThenElse :: Bool -> a -> a -> aCategory: Records
Scope: Haskell
How to Enable: {-# LANGUAGE NamedFieldPuns #-}
When to Use:
When you want to write concise record pattern bindings.
Usage Example:
greet Person{name} = putStrLn nameCategory: Prelude Control
Scope: Plutus
How to Enable: {-# LANGUAGE NoImplicitPrelude #-}
When to Use:
When working with PlutusTx which provides a custom Prelude.
Usage Example:
-- disables standard Prelude
import PlutusTx.PreludeCategory: Meta-programming
Scope: Plutus
How to Enable: {-# LANGUAGE TemplateHaskell #-}
When to Use:
Required by PlutusTx compiler to generate on-chain data encodings.
Usage Example:
$(PlutusTx.makeIsData ''MyDatum)Category: Deriving
Scope: Plutus
How to Enable: {-# LANGUAGE DeriveAnyClass #-}
When to Use:
Used to derive PlutusTx typeclass instances like ToData and FromData.
Usage Example:
data MyDatum = ... deriving (Generic, ToData)Category: Deriving
Scope: Plutus
How to Enable: {-# LANGUAGE DeriveGeneric #-}
When to Use:
Needed for DeriveAnyClass to derive ToData and similar.
Usage Example:
data MyDatum = MyDatum Int deriving (Generic)Category: Type System
Scope: Plutus
How to Enable: {-# LANGUAGE TypeApplications #-}
When to Use:
Explicitly apply types in functions like toData, fromData.
Usage Example:
PlutusTx.toData @MyDatum datum| Extension | Usage Example | When to Use | How to Enable | Category | Scope |
|---|---|---|---|---|---|
| GADTs | data Expr a where Lit :: Int -> Expr Int Add :: Expr Int -> Expr Int -> Expr Int |
When you need more precise typing in data constructors (e.g., embedded DSLs). | {-# LANGUAGE GADTs #-} |
Type System | Haskell |
| TypeFamilies | type family F a :: * type instance F Int = Bool |
When you need type-level functions associated with type classes. | {-# LANGUAGE TypeFamilies #-} |
Type System | Haskell |
| MultiParamTypeClasses | class Convertible a b where convert :: a -> b |
When a type class logically relates more than one type. | {-# LANGUAGE MultiParamTypeClasses #-} |
Type Classes | Haskell |
| FunctionalDependencies | class Convertible a b | a -> b where convert :: a -> b |
To help GHC infer types in multi-parameter type classes. | {-# LANGUAGE FunctionalDependencies #-} |
Type Classes | Haskell |
| DataKinds | data Nat = Zero | Succ Nat data Vec (n :: Nat) a = ... |
For type-level programming with promoted data constructors. | {-# LANGUAGE DataKinds #-} |
Type-Level Programming | Haskell |
| ViewPatterns | f (length -> 0) = "Empty" f _ = "Not Empty" |
When pattern matching requires function application results. | {-# LANGUAGE ViewPatterns #-} |
Pattern Matching | Haskell |
| PatternSynonyms | pattern Zero <- 0 pattern Succ n <- (n + 1) |
To simplify or abstract complex patterns. | {-# LANGUAGE PatternSynonyms #-} |
Pattern Matching | Haskell |
| OverloadedStrings | myText :: Text myText = "hello" |
When using string literals as `Text`, `ByteString`, etc. | {-# LANGUAGE OverloadedStrings #-} |
Literals | Haskell |
| TemplateHaskell | $(deriveJSON defaultOptions ''MyType) |
For compile-time code generation (e.g., JSON derivation). | {-# LANGUAGE TemplateHaskell #-} |
Meta-programming | Haskell |
| RecordWildCards | printPerson Person{..} = putStrLn name |
To reduce boilerplate in record pattern matching. | {-# LANGUAGE RecordWildCards #-} |
Records | Haskell |
| KindSignatures | data Proxy (a :: *) = Proxy |
To explicitly specify the kind of a type parameter. | {-# LANGUAGE KindSignatures #-} |
Type-Level Programming | Haskell |
| ScopedTypeVariables | f :: forall a. a -> a f x = let g :: a -> a g y = y in g x |
When you need to reuse type variables across scopes. | {-# LANGUAGE ScopedTypeVariables #-} |
Type System | Haskell |
| RankNTypes | f :: (forall a. a -> a) -> Int |
When you need higher-rank polymorphism in function types. | {-# LANGUAGE RankNTypes #-} |
Type System | Haskell |
| OverloadedLists | myVec :: Vector Int myVec = [1, 2, 3] |
To allow list literals to work with any `IsList` type. | {-# LANGUAGE OverloadedLists #-} |
Literals | Haskell |
| DeriveGeneric | data Person = Person String Int deriving (Generic) |
To derive `Generic` instance for use with libraries like Aeson. | {-# LANGUAGE DeriveGeneric #-} |
Deriving | Haskell |
| StandaloneDeriving | deriving instance Show MyType |
To derive instances for types declared elsewhere or abstract. | {-# LANGUAGE StandaloneDeriving #-} |
Deriving | Haskell |
| LambdaCase | f = \case Just x -> x; Nothing -> 0 |
For concise anonymous functions with pattern matching. | {-# LANGUAGE LambdaCase #-} |
Pattern Matching | Haskell |
| QuasiQuotes | [sql|SELECT * FROM users|] |
To embed DSLs or formatted literals inside Haskell code. | {-# LANGUAGE QuasiQuotes #-} |
Meta-programming | Haskell |
| RebindableSyntax | ifThenElse :: Bool -> a -> a -> a |
To override built-in Haskell syntax like `if`, `do`, etc. | {-# LANGUAGE RebindableSyntax #-} |
Syntax | Haskell |
| NamedFieldPuns | greet Person{name} = putStrLn name |
When you want to write concise record pattern bindings. | {-# LANGUAGE NamedFieldPuns #-} |
Records | Haskell |
| NoImplicitPrelude | -- disables standard Prelude import PlutusTx.Prelude |
When working with PlutusTx which provides a custom Prelude. | {-# LANGUAGE NoImplicitPrelude #-} |
Prelude Control | Plutus |
| TemplateHaskell | $(PlutusTx.makeIsData ''MyDatum) |
Required by PlutusTx compiler to generate on-chain data encodings. | {-# LANGUAGE TemplateHaskell #-} |
Meta-programming | Plutus |
| DeriveAnyClass | data MyDatum = ... deriving (Generic, ToData) |
Used to derive PlutusTx typeclass instances like `ToData` and `FromData`. | {-# LANGUAGE DeriveAnyClass #-} |
Deriving | Plutus |
| DeriveGeneric | data MyDatum = MyDatum Int deriving (Generic) |
Needed for `DeriveAnyClass` to derive `ToData` and similar. | {-# LANGUAGE DeriveGeneric #-} |
Deriving | Plutus |
| TypeApplications | PlutusTx.toData @MyDatum datum |
Explicitly apply types in functions like `toData`, `fromData`. | {-# LANGUAGE TypeApplications #-} |
Type System | Plutus |
Bernard Sibanda is a global Technology Entrepreneur, Web3 and Software Consultant with a deep focus on Cardano Blockchain, Midnight and Community building.
Key Positions:
- Founder, CTO, Developer Advocate cohort #1, Fullstake Developer, Cardano Ambassador, Catalyst Project Manager, DREP-WIMS:
- Co-founder of ABL Tech and Cardano Africa Live
- EBU-certified Plutus Pioneer (Plutus/Haskell)
- Cohort #1 Plutus Pioneer Developer
- Catalyst Community Reviewer & Funded Projects Manager
-
DRep for WIMS-Cardano (ID:
drep1yguj8zu48n99pv70yl6ckzt9hdgjy8yjnlqs2uyzcpafnjgu4vkul) - Intersect Developer Advocate
- Intersect Committe Member 2025-2026
- Cardano Marketer,Promoter and blogger
- Cardano Open Source Contributor
- Cardano communities and events organizer and builder
- Cardano Ambassador for South Africa
Official links:
- Stablecoins Dex
- Coxygen Global Universities
- WIMS Cardano Global
- Cardano Africa Live
- WIMS Cardano Videos
- Cardano Smart Contract Videos
- Fullstack IT Consulting
Social links: