Created
August 10, 2014 06:21
-
-
Save myuon/cd6113ca89df4b49411e to your computer and use it in GitHub Desktop.
GHC.TypeLitsと型レベルFizzBuzz ref: http://qiita.com/myuon_myon/items/dc6184f8e3d06ce3126c
This file contains hidden or 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
| {-# LANGUAGE DataKinds, TypeOperators, KindSignatures, TypeFamilies #-} | |
| {-# LANGUAGE UndecidableInstances, FlexibleInstances, FlexibleContexts #-} | |
| {-# LANGUAGE ScopedTypeVariables, GADTs, MultiParamTypeClasses, FunctionalDependencies #-} | |
| import GHC.TypeLits | |
| import Data.Type.Equality | |
| import Data.Proxy | |
| type family (a :: Nat) % (b :: Nat) :: Nat where | |
| a % b = Mod a b (CmpNat a b) | |
| type family Mod (a :: Nat) (b :: Nat) (k :: Ordering) :: Nat where | |
| Mod a b EQ = 0 | |
| Mod a b LT = a | |
| Mod a b GT = Mod (a-b) b (CmpNat (a-b) b) | |
| data FizzBuzzFlag = FizzBuzz | Fizz | Buzz | Natural Nat | |
| class ShowFB (f :: FizzBuzzFlag) where | |
| showFB :: Proxy f -> String | |
| instance ShowFB FizzBuzz where showFB _ = "FizzBuzz" | |
| instance ShowFB Fizz where showFB _ = "Fizz" | |
| instance ShowFB Buzz where showFB _ = "Buzz" | |
| instance (KnownNat n) => ShowFB (Natural n) where showFB _ = show $ natVal $ (Proxy :: Proxy n) | |
| type family ToFizzBuzz (a :: Nat) :: FizzBuzzFlag where | |
| ToFizzBuzz a = ToFizzBuzz' a (a % 3) (a % 5) | |
| type family ToFizzBuzz' (a :: Nat) (b3 :: Nat) (b5 :: Nat) :: FizzBuzzFlag where | |
| ToFizzBuzz' a 0 0 = FizzBuzz | |
| ToFizzBuzz' a 0 b5 = Fizz | |
| ToFizzBuzz' a b3 0 = Buzz | |
| ToFizzBuzz' a b3 b5 = Natural a | |
| fizzbuzz :: (ShowFB (ToFizzBuzz n)) => Proxy (n :: Nat) -> String | |
| fizzbuzz (Proxy :: Proxy m) = showFB $ (Proxy :: Proxy (ToFizzBuzz m)) | |
| {- | |
| class FizzBuzzList (n :: Nat) where | |
| fizzbuzzList :: Proxy n -> [String] -> [String] | |
| Overlapping instances for FizzBuzzList 0 | |
| arising from a use of ‘fizzbuzzList’ | |
| Matching instances: | |
| instance FizzBuzzList 0 -- Defined at TypedFizzBuzz.hs:39:10 | |
| instance (ShowFB (ToFizzBuzz n), FizzBuzzList (n - 1)) => | |
| FizzBuzzList n | |
| -- Defined at TypedFizzBuzz.hs:41:10 | |
| instance FizzBuzzList 0 where | |
| fizzbuzzList _ acc = acc | |
| instance (ShowFB (ToFizzBuzz n), FizzBuzzList (n-1)) => FizzBuzzList n where | |
| fizzbuzzList x@(Proxy :: Proxy n) acc = fizzbuzzList (Proxy :: Proxy (n-1)) (fizzbuzz x : acc) | |
| -} | |
| class FizzBuzzList' (b :: Bool) (n :: Nat) where | |
| fizzbuzzList' :: Proxy b -> Proxy n -> [String] -> [String] | |
| instance FizzBuzzList' True 0 where | |
| fizzbuzzList' _ _ acc = acc | |
| instance (ShowFB (ToFizzBuzz n), FizzBuzzList' (n == 1) (n-1)) => FizzBuzzList' False n where | |
| fizzbuzzList' _ k@(Proxy :: Proxy n) acc = fizzbuzzList' (Proxy :: Proxy (n == 1)) (Proxy :: Proxy (n-1)) ((fizzbuzz k) : acc) | |
| fizzbuzzList :: (FizzBuzzList' (n==0) n) => Proxy (n :: Nat) -> [String] | |
| fizzbuzzList x@(Proxy :: Proxy n) = fizzbuzzList' (Proxy :: Proxy (n==0)) x [] | |
| main = do | |
| putStrLn $ fizzbuzz (Proxy :: Proxy 100) | |
| mapM_ putStrLn $ fizzbuzzList (Proxy :: Proxy 10) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment