Skip to content

Instantly share code, notes, and snippets.

Created December 3, 2016 02:23
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 anonymous/98a1b60c6d0df9ff2b0fbb6acb053822 to your computer and use it in GitHub Desktop.
Save anonymous/98a1b60c6d0df9ff2b0fbb6acb053822 to your computer and use it in GitHub Desktop.
type adviser (Junk)
{-# LANGUAGE DataKinds, TypeOperators, KindSignatures, TypeFamilies #-}
{-# LANGUAGE UndecidableInstances, FlexibleInstances, FlexibleContexts #-}
{-# LANGUAGE GADTs, MultiParamTypeClasses, FunctionalDependencies #-}
-----------------------------------------------------------------------------
-- |
-- Module : TypeAdviser
-- License : Free
--
-- Stability : experimental
-- Portability : non-portable (DataKinds, TypeOperators, KindSignatures,
-- TypeFamilies, UndecidableInstances, FlexibleInstances,
-- FlexibleContexts, GADTs, MultiParamTypeClasses,
-- FunctionalDependencies)
--
-- Description : Helper functions for 'asTypeOf'
--
-- Problem: how to use non-rigid param in data family ??
--
-- > data family T a b
-- > data instance T Int b = A
-- > data instance T Char b = B
-- > tp0 (A) -- NG
-- > tp0 (A:: T Int Int) -- OK
--
-----------------------------------------------------------------------------
module Data.TypeAdviser where
import GHC.TypeLits
--import Data.Type.Equality
import Data.Typeable
-- | type of n-th argument
--
type family ArgT (a :: *) (idx :: Nat) (len :: Nat) :: * where
ArgT a 0 0 = a
ArgT (a -> b) 0 len = a
ArgT (a -> b) idx len = ArgT b (idx - 1) (len - 1)
-- | type of "return" value
--
type family RetT (a :: *) :: * where
RetT (a -> b) = RetT b
RetT a = a
type family NumArg' (a :: *) (offset :: Nat) :: Nat where
NumArg' (a -> b) offset = NumArg' b (offset + 1)
NumArg' a offset = offset
-- | num of arguments
--
type family NumArg (a :: *) :: Nat where
NumArg a = NumArg' a 0
-- | n-th type parameter (form 1 to 5)
--
-- this work for only '* kind type.
type family GetTP (a :: *) (idx :: Nat) :: * where
GetTP (f a b c d e) 0 = a
GetTP (f a b c d) 0 = a
GetTP (f a b c) 0 = a
GetTP (f a b) 0 = a
GetTP (f a) 0 = a
GetTP (f a b c d e) 1 = b
GetTP (f a b c d) 1 = b
GetTP (f a b c) 1 = b
GetTP (f a b) 1 = b
GetTP (f a b c d e) 2 = c
GetTP (f a b c d) 2 = c
GetTP (f a b c) 2 = c
GetTP (f a b c d e) 3 = d
GetTP (f a b c d) 3 = d
GetTP (f a b c d e) 4 = e
-- | replace n-th type parameter (from 1 to 5)
--
-- this work for only * kind type.
type family SetTP (a :: *) (idx :: Nat) (x :: *) :: * where
SetTP (f a b c d e) 0 x = (f x b c d e)
SetTP (f a b c d) 0 x = (f x b c d)
SetTP (f a b c) 0 x = (f x b c)
SetTP (f a b) 0 x = (f x b)
SetTP (f a) 0 x = (f x)
SetTP (f a b c d e) 1 x = (f a x c d e)
SetTP (f a b c d) 1 x = (f a x c d)
SetTP (f a b c) 1 x = (f a x c)
SetTP (f a b) 1 x = (f a x)
SetTP (f a b c d e) 2 x = (f a b x d e)
SetTP (f a b c d) 2 x = (f a b x d)
SetTP (f a b c) 2 x = (f a b x)
SetTP (f a b c d e) 3 x = (f a b c x e)
SetTP (f a b c d) 3 x = (f a b c x)
SetTP (f a b c d e) 4 x = (f a b c d x)
-- | bottom as first argument type
--
-- >>> typeName $ argT0 (undefined :: Int -> Bool -> Char -> Double -> Float)
-- "Int"
argT0 :: a -> ArgT a 0 (NumArg a)
argT0 = undefined
-- | bottom as second argument type
--
-- >>> typeName $ argT1 (undefined :: Int -> Bool -> Char -> Double -> Float)
-- "Bool"
argT1 :: a -> ArgT a 1 (NumArg a)
argT1 = undefined
-- | bottom as third argument type
--
-- >>> typeName $ argT2 (undefined :: Int -> Bool -> Char -> Double -> Float)
-- "Char"
argT2 :: a -> ArgT a 2 (NumArg a)
argT2 = undefined
-- | bottom as 4th argument type
--
-- >>> typeName $ argT3 (undefined :: Int -> Bool -> Char -> Double -> Float)
-- "Double"
argT3 :: a -> ArgT a 3 (NumArg a)
argT3 = undefined
-- | bottom as N-th argument type
--
-- >>> typeName $ argT (Proxy :: Proxy 0) (undefined :: Int -> Bool -> Char -> Double -> Float)
-- "Int"
argT :: Proxy (idx :: Nat) -> a -> ArgT a idx (NumArg a)
argT = undefined
-- | bottom as "return" value type
--
-- >>> typeName $ retT (undefined :: Int -> Bool -> Char -> Double -> Float)
-- "Float"
retT :: a -> RetT a
retT = undefined
-- | bottom as first type parameter
--
-- >>> data F a b c d = F
-- >>> typeName $ tp0 (undefined :: F Int Bool Char Double)
-- "Int"
-- >>> typeName $ tp0 ([1] :: [Int])
-- "Int"
tp0 :: a -> GetTP a 0
tp0 = undefined
-- | bottom as second type parameter
--
-- >>> data F a b c d = F
-- >>> let x = (undefined :: F Int Bool Char Double)
-- >>> typeName $ tp1 (undefined :: F Int Bool Char Double)
-- "Bool"
tp1 :: a -> GetTP a 1
tp1 = undefined
-- | bottom as third type parameter
--
-- >>> data F a b c d = F
-- >>> typeName $ tp2 (undefined :: F Int Bool Char Double)
-- "Char"
tp2 :: a -> GetTP a 2
tp2 = undefined
-- | bottom as 4th type parameter
--
-- >>> data F a b c d = F deriving (Typeable)
-- >>> typeName $ tp3 (undefined :: F Int Bool Char Double)
-- "Double"
tp3 :: a -> GetTP a 3
tp3 = undefined
-- for non-rigid param in data family.
tp0_1 :: f a -> a
tp0_1 = undefined
tp0_2 :: f a b -> a
tp0_2 = undefined
tp1_2 :: f a b -> b
tp1_2 = undefined
tp0_3 :: f a b c -> a
tp0_3 = undefined
tp1_3 :: f a b c -> b
tp1_3 = undefined
tp2_3 :: f a b c -> c
tp2_3 = undefined
tp0_4 :: f a b c d -> a
tp0_4 = undefined
tp1_4 :: f a b c d -> b
tp1_4 = undefined
tp2_4 :: f a b c d -> c
tp2_4 = undefined
tp3_4 :: f a b c d -> d
tp3_4 = undefined
-- | get type signature
--
-- >>> typeName "xxx"
-- "[Char]"
typeName :: (Typeable a) => a -> String
typeName = show . typeRep . (Proxy `as` tp0_1)
--typeName = show . typeRep . (Proxy `as` (tp0))
-- | extented asTypeOf
--
-- >>> data F a b = F deriving (Typeable)
-- >>> typeName $ (undefined :: Int -> F a Bool -> Float) `as` (tp0 . argT1) $ (undefined :: String)
-- "Int -> F [Char] Bool -> Float"
as :: a -> (a->b) -> b -> a
as x f y = const x (asTypeOf (f x) y)
-- | bottom as first type parameter replaaced type
--
-- >>> data F a b c d = F deriving (Typeable)
-- >>> typeName $ settp0 (undefined :: F Int Bool Char Double) "x"
-- "F [Char] Bool Char Double"
settp0 :: a -> b -> SetTP a 0 b
settp0 = undefined
-- | bottom as second type parameter replaaced type
--
-- >>> data F a b c d = F deriving (Typeable)
-- >>> typeName $ settp1 (undefined :: F Int Bool Char Double) "x"
--"F Int [Char] Char Double"
settp1 :: a -> b -> SetTP a 1 b
settp1 = undefined
-- | bottom as third type parameter replaaced type
--
-- >>> data F a b c d = F deriving (Typeable)
-- >>> typeName $ settp2 (undefined :: F Int Bool Char Double) "x"
--"F Int Bool [Char] Double"
settp2 :: a -> b -> SetTP a 2 b
settp2 = undefined
-- | bottom as 4th type parameter replaaced type
--
-- >>> data F a b c d = F deriving (Typeable)
-- >>> typeName $ settp3 (undefined :: F Int Bool Char Double) "x"
--"F Int Bool Char [Char]"
settp3 :: a -> b -> SetTP a 3 b
settp3 = undefined
settp0_1 :: f a -> x -> f x
settp0_1 = undefined
settp0_2 :: f a b -> x -> f x b
settp0_2 = undefined
settp1_2 :: f a b -> x -> f a x
settp1_2 = undefined
settp0_3 :: f a b c -> x -> f x b c
settp0_3 = undefined
settp1_3 :: f a b c -> x -> f a x c
settp1_3 = undefined
settp2_3 :: f a b c -> x -> f a b x
settp2_3 = undefined
settp0_4 :: f a b c d -> x -> f x b c d
settp0_4 = undefined
settp1_4 :: f a b c d -> x -> f a x c d
settp1_4 = undefined
settp2_4 :: f a b c d -> x -> f a b x d
settp2_4 = undefined
settp3_4 :: f a b c d -> x -> f a b c x
settp3_4 = undefined
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment