🎓 A1Learner
🔍
0 of 47 lessons completed

Haskell Advanced Introduction

Haskell Advanced is the next step in Haskell, where types carry more precise information. Its tools let a type record a result, a length, or a shared state.

A precise type records the result type

VInt makes a Val Int value. VBool makes a Val Bool value.

{-# LANGUAGE GADTs #-}
data Val a where
  VInt :: Int -> Val Int
  VBool :: Bool -> Val Bool

valKind :: Val a -> String
valKind (VInt _) = "int"
valKind (VBool _) = "bool"

main :: IO ()
main = do
  putStrLn (valKind (VInt 7))
  putStrLn (valKind (VBool True))

One name covers two precise shapes

Val is one type name. Its constructors build two different result types.

{-# LANGUAGE GADTs #-}
data Val a where
  VInt :: Int -> Val Int
  VBool :: Bool -> Val Bool

valShow :: Val a -> String
valShow (VInt n) = show n
valShow (VBool b) = show b

main :: IO ()
main = do
  putStrLn (valShow (VInt 7))
  putStrLn (valShow (VBool True))

A function can demand one precise shape

needInt accepts only a Val Int value. needBool accepts only a Val Bool value.

{-# LANGUAGE GADTs #-}
data Val a where
  VInt :: Int -> Val Int
  VBool :: Bool -> Val Bool

needInt :: Val Int -> Int
needInt (VInt n) = n

needBool :: Val Bool -> Bool
needBool (VBool b) = b

main :: IO ()
main = do
  print (needInt (VInt 7))
  print (needBool (VBool True))

Example

{-# LANGUAGE GADTs #-}
data Val a where
  VInt :: Int -> Val Int
  VBool :: Bool -> Val Bool

needInt :: Val Int -> Int
needInt (VInt n) = n

needBool :: Val Bool -> Bool
needBool (VBool b) = b

valKind :: Val a -> String
valKind (VInt _) = "int"
valKind (VBool _) = "bool"

main :: IO ()
main = do
  putStrLn (valKind (VInt 7))
  print (needInt (VInt 7))
  putStrLn (valKind (VBool True))
  print (needBool (VBool True))

Key points

  • Precise type: a precise type records extra information in the type itself.
  • GADT: a GADT lets each constructor choose its own result type.
  • Type family: a type family computes one type from another type.
  • DataKinds: DataKinds lifts ordinary data to the type level.
  • Lens: a lens bundles a getter and a setter for one field.
  • STM: STM gives shared changeable boxes with safe transactions.

In this example, Val is the precise type, needInt and needBool demand one shape each, and valKind names the shape of each value. The main action first names the integer shape and prints its stored number, then names the boolean shape and prints its stored boolean.

Note

this course assumes the Beginner and Intermediate courses and does not re-teach them.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Haskell Playground

Exercise

What does a precise type record in the type itself?