I will call this module SimpleReflect, since this is a poor mans form of reflection, converting code back to expressions at run time.
コードリーディング
classShow a where show x = shows x ""shows:: (Show a) => a ->ShowSshows = showsPrec 0showString::String->ShowSshowString = (++)
Expr
-- | A reflected expressiondataExpr= Expr { showExpr ::Int->ShowS-- ^ Show with the given precedence level , intExpr ::MaybeInteger-- ^ Integer value? , doubleExpr ::MaybeDouble-- ^ Floating value? , reduced ::MaybeExpr-- ^ Next reduction step }emptyExpr::ExpremptyExpr = Expr { showExpr =\_ -> showString "" , intExpr = Nothing , doubleExpr = Nothing , reduced = Nothing }
Show インスタンス
instanceShowExprwhere showsPrec p r = showExpr r p
var
var::String->Exprvar s = emptyExpr { showExpr =\_ -> showString s }
var "x"= emptyExpr { showExpr =\_ -> showString "x" }= Expr { showExpr =\_ -> showString "x" , intExpr = Nothing , doubleExpr = Nothing , reduced = Nothing }-- この値を表示すると= show (Expr { showExpr =\_ -> showString "x" })= shows (Expr { showExpr =\_ -> showString "x" }) ""= showsPrec 0 (Expr { showExpr =\_ -> showString "x" }) ""= showExpr (Expr { showExpr =\_ -> showString "x" }) 0""= (\_ -> showString "x") 0""= showString "x"""="x"++""="x"
実行結果
*Debug.SimpleReflect> var "x"x
lift
var とほぼ同じだけど Show クラスのインスタンスである型を Expr に持ち上げれる
lift::Show a => a ->Exprlift x = emptyExpr { showExpr =\p -> showsPrec p x }
lift "x"= emptyExpr { showExpr =\p -> showsPrec p x }= Expr { showExpr =\p -> showsPrec p "x" , intExpr = Nothing , doubleExpr = Nothing , reduced = Nothing }-- この値を表示すると= show (Expr { showExpr =\p -> showsPrec p "x" })= shows (Expr { showExpr =\p -> showsPrec p "x" }) ""= showsPrec 0 (Expr { showExpr =\p -> showsPrec p "x" }) ""= showExpr (Expr { showExpr =\p -> showsPrec p "x" }) 0""= (\p -> showsPrec p "x") 0""= showsPrec 0"x"""-- ここが var とは違って、文字列のShowインスタンスとなる="\"x\""
実行結果
*Debug.SimpleReflect> lift "x""x"
FromExpr
QuickCheck の Fun と同じような感じの定義
-- | Conversion from @Expr@ to other typesclassFromExpr a wherefromExpr::Expr-> ainstanceFromExprExprwhere fromExpr = idinstance (Show a,FromExpr b) =>FromExpr (a -> b) where fromExpr f a = fromExpr $ op InfixL 10" " f (lift a)