Skip to content

Instantly share code, notes, and snippets.

@nicuveo
Created October 3, 2019 00:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nicuveo/ce19538aeaada2a7d355f1dcb8ebe626 to your computer and use it in GitHub Desktop.
Save nicuveo/ce19538aeaada2a7d355f1dcb8ebe626 to your computer and use it in GitHub Desktop.
Haskell type-level fizzbuzz, version 2
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE UndecidableInstances #-}
-- no data kinds, pure type level
-- let's start by defining booleans and numbers
data True
data False
data PZ
data PS n
type P1 = PS PZ
type P2 = PS P1
type P3 = PS P2
type P4 = PS P3
type P5 = PS P4
type P6 = PS P5
type P7 = PS P6
type P8 = PS P7
type P9 = PS P8
type P10 = PS P9
type P11 = PS P10
type P12 = PS P11
type P13 = PS P12
type P14 = PS P13
type P15 = PS P14
type P16 = PS P15
-- type level functions: can a peano number be divided by 3 or 5?
class D3 n b | n -> b
instance D3 PZ True
instance D3 P1 False
instance D3 P2 False
instance D3 n b => D3 (PS (PS (PS n))) b
class D5 n b | n -> b
instance D5 PZ True
instance D5 P1 False
instance D5 P2 False
instance D5 P3 False
instance D5 P4 False
instance D5 n b => D5 (PS (PS (PS (PS (PS n))))) b
-- three new possible types, for our fizzbuzz values
data Fizz
data Buzz
data FizzBuzz
-- simple type-level mapping between our boolean types to a type-level fizzbuzz value
class GetFizzBuzz n b3 b5 v | n b3 b5 -> v
instance GetFizzBuzz n False False n
instance GetFizzBuzz n False True Fizz
instance GetFizzBuzz n True False Buzz
instance GetFizzBuzz n True True FizzBuzz
-- convenience function
-- use it in GHCI:
-- :t fb (undefined :: P12)
class FB n v | n -> v where
fb :: n -> v
instance (D3 n b3, D5 n b5, GetFizzBuzz n b3 b5 v) => FB n v where
fb = undefined
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment