Guest User

Untitled

a guest
Apr 25th, 2018
61
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.53 KB | None | 0 0
  1. {-# LANGUAGE AllowAmbiguousTypes #-}
  2. {-# LANGUAGE ConstraintKinds #-}
  3. {-# LANGUAGE DeriveGeneric #-}
  4. {-# LANGUAGE DerivingStrategies #-}
  5. {-# LANGUAGE DerivingVia #-}
  6. {-# LANGUAGE EmptyCase #-}
  7. {-# LANGUAGE FlexibleContexts #-}
  8. {-# LANGUAGE FlexibleInstances #-}
  9. {-# LANGUAGE GADTs #-}
  10. {-# LANGUAGE MultiParamTypeClasses #-}
  11. {-# LANGUAGE ScopedTypeVariables #-}
  12. {-# LANGUAGE TypeApplications #-}
  13. {-# LANGUAGE TypeFamilies #-}
  14. {-# LANGUAGE TypeInType #-}
  15. {-# LANGUAGE TypeOperators #-}
  16. {-# LANGUAGE UndecidableInstances #-}
  17. module Excluding where
  18.  
  19. import Control.DeepSeq
  20. import Data.Kind
  21. import GHC.Generics
  22.  
  23. -----
  24. -- singletons machinery
  25. -----
  26.  
  27. data family Sing :: k -> Type
  28.  
  29. class SingI (a :: k) where
  30. sing :: Sing a
  31.  
  32. data instance Sing :: Bool -> Type where
  33. SFalse :: Sing False
  34. STrue :: Sing True
  35.  
  36. instance SingI False where
  37. sing = SFalse
  38.  
  39. instance SingI True where
  40. sing = STrue
  41.  
  42. -----
  43. -- Type-level voodoo
  44. -----
  45.  
  46. type family Unless (a :: Bool) (b :: Constraint) :: Constraint where
  47. Unless True _ = ()
  48. Unless False b = b
  49.  
  50. type family Elem (x :: a) (xs :: [a]) :: Bool where
  51. Elem _ '[] = False
  52. Elem x (x:_) = True
  53. Elem x (y:xs) = Elem x xs
  54.  
  55. newtype Excluding :: [Type] -> Type -> Type where
  56. Excluding :: a -> Excluding excluded a
  57.  
  58. instance (Generic a, GNFData excluded (Rep a)) => NFData (Excluding excluded a) where
  59. rnf (Excluding x) = grnf @excluded $ from x
  60.  
  61. -----
  62. -- Generics machinery
  63. -----
  64.  
  65. class GNFData (excluded :: [Type]) f where
  66. grnf :: f a -> ()
  67.  
  68. instance GNFData e V1 where
  69. grnf x = case x of {}
  70.  
  71. instance GNFData e U1 where
  72. grnf U1 = ()
  73.  
  74. -- The important one!
  75. instance ( Unless (Elem a excluded) (NFData a)
  76. , SingI (Elem a excluded) )
  77. => GNFData excluded (K1 i a) where
  78. grnf (K1 x) = case sing @Bool @(Elem a excluded) of
  79. STrue -> ()
  80. SFalse -> rnf x
  81. {-# INLINEABLE grnf #-}
  82.  
  83. instance GNFData e a => GNFData e (M1 i c a) where
  84. grnf = grnf @e . unM1
  85. {-# INLINEABLE grnf #-}
  86.  
  87. instance (GNFData e a, GNFData e b) => GNFData e (a :*: b) where
  88. grnf (x :*: y) = grnf @e x `seq` grnf @e y
  89. {-# INLINEABLE grnf #-}
  90.  
  91. instance (GNFData e a, GNFData e b) => GNFData e (a :+: b) where
  92. grnf (L1 x) = grnf @e x
  93. grnf (R1 x) = grnf @e x
  94. {-# INLINEABLE grnf #-}
  95.  
  96. -----
  97. -- Example
  98. -----
  99.  
  100. data MyBigType
  101. = MyBigType {
  102. f1 :: Int
  103. , f2 :: Double
  104. , f3 :: (Int -> Char)
  105. , f4 :: Char
  106. } deriving stock Generic
  107. deriving NFData via (Excluding '[Int -> Char] MyBigType)
  108.  
  109. main :: IO ()
  110. main = do
  111. let mbt = MyBigType 1 2.0 undefined '3'
  112. mbt `deepseq` putStrLn "Done"
Add Comment
Please, Sign In to add comment