Advertisement
Guest User

Untitled

a guest
Jan 27th, 2015
175
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.46 KB | None | 0 0
  1. {-# LANGUAGE FlexibleInstances #-}
  2. -- | Monoids with holes. The 'HoleyMonoid' allows building monoidal values of which certain components are to be filled in later. For example:
  3. --
  4. -- > > let holey = now "x = "
  5. -- > . later show
  6. -- > . now ", y = "
  7. -- > . later show
  8. -- > > run holey 3 5
  9. -- > "x = 3, y = 5"
  10. --
  11. -- This module is intended to be imported in qualified fashion, e.g.
  12. --
  13. -- > import qualified Data.HoleyMonoid as HM
  14.  
  15. module Data.HoleyMonoid (
  16. HoleyMonoid, run,
  17. now, later, map
  18.  
  19. ) where
  20.  
  21. import Prelude hiding (id, (.), map)
  22. import Control.Category
  23. import Data.Monoid
  24.  
  25. -- | The type of a monoid with holes. The underlying monoid is represented by
  26. -- type parameter @m@. The @r@ is the result type and stays polymorphic until the
  27. -- very last moment when 'run' is called. The last argument @a@ is always a
  28. -- function with zero or more arguments, finally resulting in @r@. Ordering the
  29. -- arguments in this order allows holey monoids to be composed using `.`, stacking the
  30. -- expected arguments. Note that the `Monoid` constraint is only used in the
  31. -- identity 'HoleyMonoid' and in composing two 'HoleyMonoid's.
  32. newtype HoleyMonoid m r a = HoleyMonoid { runHM :: (m -> r) -> a }
  33.  
  34. instance Monoid m => Monoid (HoleyMonoid m r (a -> r)) where
  35. mappend m n = HoleyMonoid (\k a -> runHM m (\b1 -> runHM n (\b2 -> k (b1 <> b2)) a) a)
  36. mempty = HoleyMonoid (\k a -> k mempty)
  37.  
  38. instance Monoid m => Category (HoleyMonoid m) where
  39. id = now mempty
  40. f . g = f `bind` \a -> g `bind` \b -> now (a `mappend` b)
  41.  
  42. -- | Insert a constant monoidal value.
  43. now :: m -> HoleyMonoid m r r
  44. now a = HoleyMonoid ($ a)
  45.  
  46. -- | Monadic indexed bind for holey monoids.
  47. bind :: HoleyMonoid m b c -> (m -> HoleyMonoid n a b) -> HoleyMonoid n a c
  48. m `bind` f = HoleyMonoid $ \k -> runHM m (\a -> runHM (f a) k)
  49.  
  50. -- | Insert a monoidal value that is not specified until the computation is
  51. -- 'run'. The argument that is expected later is converted to the monoid type
  52. -- using the given conversion function.
  53. later :: (a -> m) -> HoleyMonoid m r (a -> r)
  54. later f = HoleyMonoid (. f)
  55.  
  56. -- | Convert between underlying 'Monoid' types.
  57. map :: (m -> n) -> HoleyMonoid m r a -> HoleyMonoid n r a
  58. map g m = HoleyMonoid (\k -> runHM m (k . g))
  59.  
  60. -- | Run the computation, resulting in a function that still expects some
  61. -- arguments. The number of arguments that is still expected will be equal to the
  62. -- number of 'later's the computation is built of.
  63. run :: HoleyMonoid m m a -> a
  64. run m = runHM m id
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement