packages feed

ap-reflect (empty) → 0.1.0.0

raw patch · 4 files changed

+187/−0 lines, 4 filesdep +basesetup-changed

Dependencies added: base

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2014, Oleg Baev++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Nickolay Kudasov nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple
+main = defaultMain
+ ap-reflect.cabal view
@@ -0,0 +1,26 @@+name:                ap-reflect
+version:             0.1.0.0
+synopsis:            Partial evaluation reflection a la simple-reflect.
+-- description:         
+license:             BSD3
+license-file:        LICENSE
+author:              Oleg Baev
+maintainer:          odbaev@yandex.ru
+homepage:            https://github.com/cmc-msu-ai/ap-reflect
+bug-reports:         https://github.com/cmc-msu-ai/ap-reflect/issues
+-- copyright:           
+-- category:            
+build-type:          Simple
+cabal-version:       >=1.10
+
+library
+  default-language:    Haskell2010
+  hs-source-dirs:      src
+  ghc-options:         -Wall
+  exposed-modules:     Debug.Reflect
+  -- other-modules:       
+  build-depends:       base ==4.6.*
+
+Source-Repository head
+  Type:                 git
+  Location:             https://github.com/cmc-msu-ai/ap-reflect.git
+ src/Debug/Reflect.hs view
@@ -0,0 +1,129 @@+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE DeriveFunctor #-}++module Debug.Reflect where++import Control.Applicative (Applicative(..), (<$>))+import Data.List (findIndex, isInfixOf, isPrefixOf)+import Data.Char (isAlpha)+++-- | analog of @(->)@+infixr 5 ~>+data (~>) a b = Fn String (a -> b) -- ^ name and function itself+  deriving (Functor)++-- | gets function+fromFn :: (a ~> b) -> (a -> b)+fromFn (Fn _ f) = f++instance Show (a ~> b) where+  show (Fn s _) = s++-- | adds brackets+parens :: String -> String+parens s = "(" ++ s ++ ")"++-- | checks whether function is infix+isInfixFn :: String -> Bool+isInfixFn = not . any isAlpha++-- | shows function with its argument+showFn :: String -> String -> String+showFn f x = if isInfixFn f then x ++ " " ++ f else f ++ " " ++ x++-- | translates function @(a -> b -> c)@ into @(a ~> b ~> c)@+makeFn2 :: Show a => String -> (a -> b -> c) -> (a ~> b ~> c)+makeFn2 s f = Fn s $ \x -> Fn (showFn s (show x)) (f x)++-- | makes binary operation+makeBinOp :: Show a => String -> (a -> b -> c) -> (a ~> b ~> c)+makeBinOp s f = Fn s' $ \x -> Fn (parens $ showFn s (show x)) (f x)+  where s' = if isInfixFn s then parens s else s++-- | reflected expression+data Ap b+  = Val b+  | forall a. Show a => Ap (a ~> b) :$ Ap a++-- | checks whether expression is @Val@+isVal :: Ap a -> Bool+isVal (Val _) = True+isVal _ = False++-- | balances brackets+balanceParens :: String -> String+balanceParens s = if "<*>" `isInfixOf` s then parens s else s++-- | balances brackets+parensFr :: String -> String+parensFr s = if ' ' `elem` s then parens s else s++-- | shows operation application+showOp :: String -> String -> String -> String+showOp op f x+    | isInfixFn op = f ++ " " ++ op ++ " " ++ balanceParens x+    | otherwise = op ++ " " ++ f ++ " " ++ parensFr x++-- | shows operation application+showF :: String -> String -> String+showF f x+    | "fmap" `isPrefixOf` f = f ++ " " ++ parensFr x+    | otherwise = f ++ " " ++ balanceParens x++instance Show a => Show (Ap a) where+  show (Val x) = show x+  show (op :$ f :$ x) = showOp (show op) (show f) (show x)+  show (f :$ x) = showF (show f) (show x)++-- | analog of @fmap@ using @(~>)@+fmap' :: Functor f => (a ~> b) ~> f a ~> f b+fmap' = makeFn2 "<$>" (fmap . fromFn)++-- | analog of @pure@ using @(~>)@+pure' :: Applicative f => a ~> f a+pure' = Fn "pure" pure++-- | analog of @\<*>@ using @(~>)@+ap' :: (Show (f (a ~> b)), Applicative f) => f (a ~> b) ~> f a ~> f b+ap' = Fn "<*>" $ \f -> Fn (show f ++ " <*>") $ \x -> fromFn <$> f <*> x++-- | analog of  @\<$>@+infix 6 -$-+(-$-) :: (Show (f a), Functor f) => (a ~> b) -> f a -> Ap (f b)+f -$- x = Val fmap' :$ Val f :$ Val x++-- | analog of @\<*>@+infixl 5 -*-+(-*-) :: (Show (f (a ~> b)), Show (f a), Applicative f) => Ap (f (a ~> b)) -> f a -> Ap (f b)+f -*- x = Val ap' :$ f :$ Val x++-- | analog of @pure@+pure'' :: (Show a, Applicative f) => a -> Ap (f a)+pure'' x = Val pure' :$ Val x++-- | analog of @fmap@+fmap'' :: (Show (f a), Functor f) => (a ~> b) -> f a -> Ap (f b)+fmap'' f x = Val (makeFn2 "fmap" (fmap . fromFn)) :$ Val f :$ Val x++-- | reduces an expression+reduce'' :: Ap a -> Ap a+reduce'' (Val (Fn _ f) :$ Val x) = Val (f x)+reduce'' (Val f :$ x) = Val f :$ reduce'' x+reduce'' (f :$ x) = reduce'' f :$ x+reduce'' v = v++-- | reduces (evaluates) an expression once+reduce' :: Show a => Ap a -> Ap a+reduce' x+    | isVal x = x+    | otherwise = head $ filter (\x' -> show x' /= show x) xs+    where xs = iterate reduce'' x++-- | gets all reduction steps when evaluating an expression+reductions :: Show a => Ap a -> [Ap a]+reductions x = take (n + 1) xs+  where+    Just n = findIndex isVal xs+    xs = iterate reduce' x