Created
March 29, 2019 17:03
-
-
Save Solonarv/6f5eefbb4dfdad8892f2440de1020d6a to your computer and use it in GitHub Desktop.
Should be correct, but takes so long to compile that I have no idea if it actually works.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# OPTIONS_GHC -Wno-unticked-promoted-constructors -freduction-depth=0 #-} | |
{-# LANGUAGE AllowAmbiguousTypes #-} | |
{-# LANGUAGE DataKinds #-} | |
{-# LANGUAGE ExplicitForAll #-} | |
{-# LANGUAGE FlexibleInstances #-} | |
{-# LANGUAGE MultiParamTypeClasses #-} | |
{-# LANGUAGE PolyKinds #-} | |
{-# LANGUAGE TypeApplications #-} | |
{-# LANGUAGE TypeFamilies #-} | |
{-# LANGUAGE TypeOperators #-} | |
{-# LANGUAGE UndecidableInstances #-} | |
import GHC.TypeLits | |
type m `Divides` n = (m `Mod` n) == 0 | |
type family Range l h where | |
Range l h = If (l <=? h) (l : Range (l+1) h) '[] | |
type family (==) (x :: k) (y :: k) :: Bool where | |
x == x = True | |
_ == _ = False | |
type family If p thn els where | |
If True thn _ = thn | |
If False _ els = els | |
------------------------------------------------------------------------------- | |
type family FizzBuzzOnce (assocs :: [(Nat, Symbol)]) (n :: Nat) :: ErrorMessage where | |
FizzBuzzOnce '[] n = ShowType n | |
FizzBuzzOnce ('(m, sym):as) n = If (m `Divides` n) (FizzBuzzHelper as n (Text sym)) (FizzBuzzOnce as n) | |
type family FizzBuzzHelper (assocs :: [(Nat, Symbol)]) (n :: Nat) (acc :: ErrorMessage) :: ErrorMessage where | |
FizzBuzzHelper '[] _ acc = acc | |
FizzBuzzHelper ('(m, sym):as) n acc = FizzBuzzHelper as n (If (m `Divides` n) (Text sym :<>: acc) acc) | |
type family FizzBuzzAll (assocs :: [(Nat, Symbol)]) (ns :: [Nat]) :: ErrorMessage where | |
FizzBuzzAll as '[] = Text "-- Done." | |
FizzBuzzAll as (n : ns) = FizzBuzzOnce as n :$$: FizzBuzzAll as ns | |
class FizzBuzzInst as ns where | |
doFizzBuzz :: forall xx. xx | |
doFizzBuzz = undefined | |
instance TypeError (FizzBuzzAll as ns) => FizzBuzzInst as ns | |
------------------------------------------------------------------------------- | |
main = doFizzBuzz @[(3, "Fizz"), (5, "Buzz")] @(Range 1 100) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment