가연 빈자를 받는 함수

 
{-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE AllowAmbiguousTypes #-} module Printf () where import Data.Kind (Type) import Data.Monoid ((<>)) import Data.Proxy (Proxy(..)) import GHC.TypeLits import Data.Coerce symVal :: forall sym. KnownSymbol sym => String symVal = symbolVal (Proxy @sym) data Nil = Nil data (a :: Either Type Symbol) :<< (b :: Either Nil k1) infixr 5 :<< class HasPrintf a where type Printf a :: Type printf :: String -> Printf a instance HasPrintf (Left 'Nil) where type Printf (Left 'Nil) = String printf = id instance HasPrintf tail => HasPrintf (Right tail) where type Printf (Right tail) = Printf tail printf = printf @tail instance (KnownSymbol sym, HasPrintf tail) => HasPrintf (Right sym :<< tail) where type Printf (Right sym :<< tail) = Printf tail printf string = printf @tail (string <> symVal @sym) instance (Show param, HasPrintf tail) => HasPrintf (Left param :<< tail) where type Printf (Left param :<< tail) = param -> Printf tail printf string param = printf @tail (string <> show param) safePrintf :: forall a. HasPrintf a => Printf a safePrintf = printf @a mempty