-- weird.hs: conjures some weird or unintuitive functions -- -- Copyright (C) 2025 Rudy Matela -- Distributed under the 3-Clause BSD licence (see the file LICENSE). -- -- This file conjures some weird or unintuitive functions. -- It is here to make sure we do not overprune! -- -- For simplicity, -- we do not use partial definitions here. -- We use fully defined functions to conjure themselves. import Conjure import Test.LeanCheck.Error (errorToNothing) import Data.Maybe (isNothing) -- | An undefined function. bottom :: Int bottom = undefined -- | A specification for the above undefined function. bottomSpec :: Int -> [Property] bottomSpec bottom = [property $ isError bottom] where isError = isNothing . errorToNothing -- TODO: add to LeanCheck.Error? -- | xor for integers -- -- returns the sum but only when one of the arguments is 0 (^^^) :: Int -> Int -> Int 0 ^^^ y = y x ^^^ 0 = x _ ^^^ _ = 0 -- | inc or square based on boolean argument -- except for 0 where the answer is swapped isq :: Bool -> Int -> Int isq False 0 = 0 isq True 0 = 1 isq False x = x + 1 isq True x = x * x main :: IO () main = do -- We try to ask Conjure to generate undefined -- Conjure complains about not being able to reify specification. -- Fair enough: there's no way to distinguish an undefined function -- from an empty specification. conjure "bottom" bottom [] -- With a spec, Conjure finds the "implementation" conjureFromSpec "bottom" bottomSpec [] conjure "isq" isq ingredients conjure "^^^" (^^^) ingredients conjure "^^^" (^^^) $ ingredients ++ [singlePattern] -- This example is quite the degenerate case, -- it takes a while to conjure even with just 2 ingredients. -- I am leaving it commented-out for now... -- conjure "thirty" thirty [pr (0::Int), fun "+" ((+) :: Int -> Int -> Int)] ingredients :: [Ingredient] ingredients = [ con (0::Int) , con (1::Int) , fun "+" ((+) :: Int -> Int -> Int) , fun "*" ((*) :: Int -> Int -> Int) , fun "==" ((==) :: Int -> Int -> Bool) , fun "&&" (&&) , fun "||" (||) , iif (undefined :: Int) -- guard does not play well with usePatterns = False yet ] -- | returns the sum when one of the arguments is 0 -- -- Naming: thirty/30, sum of __3__, when one is __0__ thirty :: Int -> Int -> Int -> Int thirty 0 y z = y + z thirty x 0 z = x + z thirty x y 0 = x + y thirty x y z = 0