Guest User

Untitled

a guest
Feb 22nd, 2018
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.84 KB | None | 0 0
  1. {-# LANGUAGE RankNTypes #-}
  2. {-# LANGUAGE TypeFamilies #-}
  3. {-# LANGUAGE KindSignatures #-}
  4. {-# LANGUAGE ConstraintKinds #-}
  5. {-# LANGUAGE FlexibleInstances #-}
  6. {-# LANGUAGE ScopedTypeVariables #-}
  7. {-# LANGUAGE MultiParamTypeClasses #-}
  8. {-# LANGUAGE DuplicateRecordFields #-}
  9. {-# LANGUAGE FunctionalDependencies #-}
  10.  
  11. import GHC.Exts
  12.  
  13. class Handler h a where
  14. type HCtx h a :: Constraint
  15.  
  16. handle :: HCtx h a => h a -> a -> String
  17.  
  18. class Handler h b => Middleware m h a b where
  19. type MCtx m a b :: Constraint
  20.  
  21. extendHandler :: (Handler h b, HCtx h b, MCtx m a b) =>
  22. m h a b -> h b -> (a -> String)
  23.  
  24. data BaseHandler a = BaseHandler (a -> String)
  25.  
  26. data ConstrainedHandler (p :: Constraint) a =
  27. ConstrainedHandler (p => a -> String)
  28.  
  29. data ConstrainedMiddleware
  30. (p :: Constraint) h a b = ConstrainedMiddleware {
  31. getMiddleware :: ((Handler h b, HCtx h b, p) => h b -> a -> String)
  32. }
  33.  
  34. instance Handler BaseHandler a where
  35. type HCtx BaseHandler a = ()
  36.  
  37. handle (BaseHandler h) = h
  38.  
  39. instance Handler (ConstrainedHandler p) a where
  40. type HCtx (ConstrainedHandler p) a = p
  41.  
  42. handle (ConstrainedHandler h) = h
  43.  
  44. instance (Handler h b) =>
  45. Middleware (ConstrainedMiddleware p) h a b where
  46. type MCtx (ConstrainedMiddleware p) a b = p
  47.  
  48. extendHandler (ConstrainedMiddleware m) h = m h
  49.  
  50. composeHandlers ::
  51. forall f g a.
  52. (Handler f a, Handler g a) =>
  53. f a ->
  54. g a ->
  55. ConstrainedHandler ((HCtx f a), (HCtx g a)) a
  56. composeHandlers f g = ConstrainedHandler $ \c ->
  57. "(compose-handler " ++ (handle f c) ++ " " ++ (handle g c) ++ ")"
  58.  
  59. applyMiddleware ::
  60. forall m h a b.
  61. (Handler h b,
  62. Middleware m h a b) =>
  63. m h a b ->
  64. h b ->
  65. ConstrainedHandler (HCtx h b, MCtx m a b) a
  66. applyMiddleware m h = ConstrainedHandler $ extendHandler m h
  67.  
  68.  
  69. class HasFoo a where
  70. getFoo :: a -> String
  71.  
  72. class HasBar a where
  73. getBar :: a -> String
  74.  
  75. fooHandler :: forall a. ConstrainedHandler (HasFoo a) a
  76. fooHandler = ConstrainedHandler $ \x ->
  77. "(foo-handler " ++ (getFoo x) ++ ")"
  78.  
  79. barHandler :: forall a. ConstrainedHandler (HasBar a) a
  80. barHandler = ConstrainedHandler $ \x ->
  81. "(bar-handler " ++ (getBar x) ++ ")"
  82.  
  83. barMiddleware ::
  84. forall h a b.
  85. ConstrainedMiddleware (SetBar a b) h a b
  86. barMiddleware = ConstrainedMiddleware $ \h x ->
  87. handle h $ setBar x "injectedBarVal"
  88.  
  89. combinedHandler = composeHandlers fooHandler barHandler
  90.  
  91. extendedHandler = applyMiddleware barMiddleware combinedHandler
  92.  
  93.  
  94. data Config = Config { foo :: String, bar :: String }
  95.  
  96. data PartialConfig = PartialConfig { foo :: String }
  97.  
  98. instance HasFoo Config where
  99. getFoo = foo
  100.  
  101. instance HasBar Config where
  102. getBar = bar
  103.  
  104. class HasBar b => SetBar a b | a -> b where
  105. setBar :: a -> String -> b
  106.  
  107. instance SetBar PartialConfig Config where
  108. setBar (PartialConfig fooVal) barVal = Config { foo = fooVal, bar = barVal }
  109.  
  110. result = handle extendedHandler $ PartialConfig { foo = "fooVal" }
  111.  
  112. main :: IO ()
  113. main = putStrLn result
Add Comment
Please, Sign In to add comment