Copyright | (c) 2021 Rudy Matela |
---|---|
License | 3-Clause BSD (see the file LICENSE) |
Maintainer | Rudy Matela <rudy@matela.com.br> |
Safe Haskell | None |
Language | Haskell2010 |
A library for Conjuring function implementations from tests or partial definitions. (a.k.a.: functional inductive programming)
This is currently an experimental tool in its early stages, don't expect much from its current version. It is just a piece of curiosity in its current state.
Step 1: declare your partial function
square :: Int -> Int square 0 = 0 square 1 = 1 square 2 = 4
Step 2: declare a list with the potential building blocks:
background :: [Expr] background = [ val (0::Int) , val (1::Int) , value "+" ((+) :: Int -> Int -> Int) , value "*" ((*) :: Int -> Int -> Int) , value "==" ((==) :: Int -> Int -> Bool) ]
Including equality ==
over the given type is a good rule of thumb to
improve performance.
Step 3: call conjure and see your generated function:
> conjure "square" square background square :: Int -> Int -- looking through 815 candidates, 100% match, 3/3 assignments square x = x * x
Synopsis
- conjure :: Conjurable f => String -> f -> [Expr] -> IO ()
- val :: (Typeable a, Show a) => a -> Expr
- value :: Typeable a => String -> a -> Expr
- ifFor :: Typeable a => a -> Expr
- data Expr
- conjpure :: Conjurable f => String -> f -> [Expr] -> (Int, Int, [(Int, Expr)])
- data Args = Args {
- maxTests :: Int
- maxSize :: Int
- maxEquationSize :: Int
- maxRecursionSize :: Int
- args :: Args
- conjureWith :: Conjurable f => Args -> String -> f -> [Expr] -> IO ()
- conjpureWith :: Conjurable f => Args -> String -> f -> [Expr] -> (Int, Int, [(Int, Expr)])
Basic use
conjure :: Conjurable f => String -> f -> [Expr] -> IO () Source #
Conjures an implementation of a partially defined function.
Takes a String
with the name of a function,
a partially-defined function from a conjurable type,
and a list of building blocks encoded as Expr
s.
For example, given:
square :: Int -> Int square 0 = 0 square 1 = 1 square 2 = 4 background :: [Expr] background = [ val (0::Int) , val (1::Int) , value "+" ((+) :: Int -> Int -> Int) , value "*" ((*) :: Int -> Int -> Int) , value "==" ((==) :: Int -> Int -> Bool) ]
The conjure function does the following:
> conjure "square" square background square :: Int -> Int -- looking through 815 candidates, 100% match, 3/3 assignments square x = x * x
value :: Typeable a => String -> a -> Expr #
O(1).
It takes a string representation of a value and a value, returning an
Expr
with that terminal value.
For instances of Show
, it is preferable to use val
.
> value "0" (0 :: Integer) 0 :: Integer
> value "'a'" 'a' 'a' :: Char
> value "True" True True :: Bool
> value "id" (id :: Int -> Int) id :: Int -> Int
> value "(+)" ((+) :: Int -> Int -> Int) (+) :: Int -> Int -> Int
> value "sort" (sort :: [Bool] -> [Bool]) sort :: [Bool] -> [Bool]
ifFor :: Typeable a => a -> Expr Source #
Creates an if Expr
of the type of the given proxy.
> ifFor (undefined :: Int) if :: Bool -> Int -> Int -> Int
> ifFor (undefined :: String) if :: Bool -> [Char] -> [Char] -> [Char]
You need to provide this as part of your building blocks on the background if you want recursive functions to be considered and produced.
Values of type Expr
represent objects or applications between objects.
Each object is encapsulated together with its type and string representation.
Values encoded in Expr
s are always monomorphic.
An Expr
can be constructed using:
val
, for values that areShow
instances;value
, for values that are notShow
instances, like functions;:$
, for applications betweenExpr
s.
> val False False :: Bool
> value "not" not :$ val False not False :: Bool
An Expr
can be evaluated using evaluate
, eval
or evl
.
> evl $ val (1 :: Int) :: Int 1
> evaluate $ val (1 :: Int) :: Maybe Bool Nothing
> eval 'a' (val 'b') 'b'
Show
ing a value of type Expr
will return a pretty-printed representation
of the expression together with its type.
> show (value "not" not :$ val False) "not False :: Bool"
Expr
is like Dynamic
but has support for applications and variables
(:$
, var
).
The var
underscore convention:
Functions that manipulate Expr
s usually follow the convention
where a value
whose String
representation starts with '_'
represents a var
iable.
Instances
Eq Expr | O(n). Does not evaluate values when comparing, but rather uses their representation as strings and their types. This instance works for ill-typed expressions. |
Ord Expr | O(n). Does not evaluate values when comparing, but rather uses their representation as strings and their types. This instance works for ill-typed expressions. Expressions come first
when they have smaller complexity ( |
Show Expr | Shows > show (value "not" not :$ val False) "not False :: Bool" |
Advanced use
Arguments to be passed to conjureWith
or conjpureWith
.
See args
for the defaults.
Args | |
|
Default arguments to conjure.
- 60 tests
- functions of up to 9 symbols
- pruning with equations up to size 5
- recursion up to 60 symbols.
conjureWith :: Conjurable f => Args -> String -> f -> [Expr] -> IO () Source #