sbv-9.0: Documentation/SBV/Examples/Misc/Definitions.hs
-----------------------------------------------------------------------------
-- |
-- Module : Documentation.SBV.Examples.Misc.Definitions
-- Copyright : (c) Levent Erkok
-- License : BSD3
-- Maintainer: erkokl@gmail.com
-- Stability : experimental
--
-- Demonstrates how we can add actual SMT-definitions for functions
-- that cannot otherwise be defined in SBV. Typically, these are used
-- for recursive definitions.
-----------------------------------------------------------------------------
{-# OPTIONS_GHC -Wall -Werror #-}
module Documentation.SBV.Examples.Misc.Definitions where
import Data.SBV
-- | Sum of numbers from 0 to the given number.
-- Note that this cannot be defined as a regular Haskell function, as
-- it wouldn't terminate as it recurses on a symbolic argument.
sumToN :: SInteger -> SInteger
sumToN = uninterpret "sumToN"
-- | Add the definition of sum to the SMT solver. Note that SBV
-- performs no checks on your definition, neither that it is
-- well formed, or even has the correct type!
defineSum :: Symbolic ()
defineSum = addSMTDefinition "sumToN"
[ "(define-fun-rec sumToN ((x Int)) Int"
, " (ite (<= x 0)"
, " 0"
, " (+ x (sumToN (- x 1)))))"
]
-- | A simple proof using 'sumToN'. We get a failure, because we haven't
-- given the solver the definition, and thus it goes completely uninterpreted.
--
-- We have:
--
-- >>> badExample
-- Falsifiable. Counter-example:
-- sumToN :: Integer -> Integer
-- sumToN _ = 0
--
-- Since 'sumToN' remains uninterpreted, the solver gave us a model that obviously
-- fails the property.
badExample :: IO ThmResult
badExample = prove $ do
let check = sumToN 5 .== 15 -- Should fail, even though 5*6/2 = 15
pure check :: Predicate
-- | Same example, except this time we give the solver the definition of the function,
-- and thus the proof goes through.
--
-- We have:
--
-- >>> goodExample
-- Q.E.D.
--
-- In this case, the solver has the definition, and proves the predicate as expected.
goodExample :: IO ThmResult
goodExample = prove $ do
defineSum
let check = sumToN 5 .== 15 -- Should fail, even though 5*6/2 = 15
pure check :: Predicate