Guest User

Untitled

a guest
Jun 24th, 2018
79
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.32 KB | None | 0 0
  1. {-# LANGUAGE FlexibleContexts #-}
  2. {-# LANGUAGE MultiParamTypeClasses #-}
  3. {-# LANGUAGE RankNTypes #-}
  4. {-# LANGUAGE ScopedTypeVariables #-}
  5. {-# LANGUAGE UndecidableInstances #-}
  6. module AdHocInstances(
  7. Group(..),
  8. GroupExpr(),
  9. adhocGroup
  10. ) where
  11.  
  12. import Data.Semigroup
  13.  
  14. import Control.Monad (ap)
  15.  
  16. import Data.Proxy
  17. import Data.Reflection
  18.  
  19. class (Semigroup a, Monoid a) => Group a where
  20. inv :: a -> a
  21.  
  22. gtimes :: (Integral b) => b -> a -> a
  23. gtimes b a
  24. | b < 0 = inv (stimes (negate b) a)
  25. | b == 0 = mempty
  26. | otherwise = stimes b a
  27.  
  28. --------------------------------------------------
  29.  
  30. newtype GroupExpr a =
  31. GroupExpr { runGroup :: forall r. Group r => (a -> r) -> r }
  32.  
  33. instance Functor GroupExpr where
  34. fmap f ma = GroupExpr $ \k -> runGroup ma (k . f)
  35.  
  36. instance Applicative GroupExpr where
  37. pure = return
  38. (<*>) = ap
  39.  
  40. instance Monad GroupExpr where
  41. return a = GroupExpr $ \k -> k a
  42. ma >>= f = GroupExpr $ \k ->
  43. runGroup ma $ \a -> runGroup (f a) k
  44.  
  45. instance Semigroup (GroupExpr a) where
  46. GroupExpr ma <> GroupExpr mb = GroupExpr $ \k -> ma k <> mb k
  47. stimes n (GroupExpr ma) = GroupExpr $ \k -> stimes n (ma k)
  48.  
  49. instance Monoid (GroupExpr a) where
  50. mempty = GroupExpr $ const mempty
  51. mappend = (<>)
  52.  
  53. instance Group (GroupExpr a) where
  54. inv (GroupExpr ma) = GroupExpr $ \k -> inv (ma k)
  55. gtimes n (GroupExpr ma) = GroupExpr $ \k -> gtimes n (ma k)
  56.  
  57. ----------------------------------------------------
  58.  
  59. newtype AdHocGroup s a = AsGroup { forgetGroup :: a }
  60. deriving (Eq, Ord)
  61.  
  62. data GroupOp a =
  63. GroupOp { groupUnit :: a
  64. , groupAppend :: a -> a -> a
  65. , groupInv :: a -> a
  66. , groupTimes :: forall b. Integral b => b -> a -> a
  67. }
  68.  
  69. groupOp :: a -> (a -> a -> a) -> (a -> a) -> GroupOp a
  70. groupOp unit append inv' = GroupOp unit append inv' gtimes'
  71. where
  72. gtimes' b a
  73. | b < 0 = inv' (stimes' (negate b) a)
  74. | b == 0 = unit
  75. | otherwise = stimes' b a
  76.  
  77. stimes' n a = loop unit a n
  78. loop accum a n
  79. | n == 0 = accum
  80. | even n = loop accum (a `append` a) (n `quot` 2)
  81. | otherwise = loop (accum `append` a) (a `append` a) (n `quot` 2)
  82.  
  83. instance (Reifies s (GroupOp a)) => Semigroup (AdHocGroup s a) where
  84. AsGroup a <> AsGroup b = AsGroup $ groupAppend (reflect (Proxy :: Proxy s)) a b
  85. stimes = gtimes
  86.  
  87. instance (Reifies s (GroupOp a)) => Monoid (AdHocGroup s a) where
  88. mempty = AsGroup $ groupUnit (reflect (Proxy :: Proxy s))
  89. mappend = (<>)
  90.  
  91. instance (Reifies s (GroupOp a)) => Group (AdHocGroup s a) where
  92. inv (AsGroup a) = AsGroup $ groupInv (reflect (Proxy :: Proxy s)) a
  93. gtimes n (AsGroup a) = AsGroup $ groupTimes (reflect (Proxy :: Proxy s)) n a
  94.  
  95. using :: AdHocGroup s a -> Proxy s -> AdHocGroup s a
  96. using = const
  97.  
  98. adhocGroup :: a -> (a -> a -> a) -> (a -> a) ->
  99. GroupExpr a ->
  100. a
  101. adhocGroup unit append inv' expr =
  102. reify (groupOp unit append inv') $ \p ->
  103. forgetGroup (runGroup expr AsGroup `using` p)
  104.  
  105. --------------------------------------
  106.  
  107. example1 :: Int
  108. example1 = adhocGroup 0 (+) negate $
  109. pure 1 <> inv (pure 2) <> mempty
  110.  
  111. example2 :: Rational -> Rational
  112. example2 x = adhocGroup 1 (*) recip $
  113. pure x <> inv (pure x <> pure 2)
  114.  
  115. example3 :: Bool -> Bool -> Bool
  116. example3 x y = adhocGroup False xor id $
  117. pure x <> inv (pure y) <> inv (pure x)
  118. where xor = (/=)
Add Comment
Please, Sign In to add comment