Integer -> Bool
function is true for at least one number is computationally insoluble. However, something that at first glance seems just such an oracle (namely, a function (Integer -> Bool) -> Maybe Integer
) will be described in this article. data Nat = Zero | Succ Nat deriving (Eq, Ord, Show)
Succ
from the word successor).Integer
) over numbers in this representation: instance Num Nat where Zero + y = y Succ x + y = Succ (x + y) Zero * y = Zero Succ x * y = y + (x * y) fromInteger 0 = Zero fromInteger n = Succ (fromInteger (n-1))
Integer
.(Nat -> Bool) -> Maybe Nat
, the result of which will be a number on which the input function returns True
, or Nothing
if there is no such number. The first approximation can be, for example, a similar function: lyingSearch :: (Nat -> Bool) -> Nat lyingSearch f | f Zero = Zero | otherwise = Succ (lyingSearch (f . Succ))
f Zero == True
, then the return value will be Zero
- true. Otherwise, the function will return x+1
, where x
- the value on which the function f(x+1)
is true is also true.lyingSearch
: in the case when there is no desired number, the function will go into recursion at each step and return, in fact, infinity: Succ (Succ (Succ (...
, where nesting will never end). Due to Haskell
laziness, this is a normal situation, but infinity is not the desired answer — hence, in this case, the function is “lying”.lyingSearch
function. Consider the search
function defined as: search f | f possibleMatch = Just possibleMatch | otherwise = Nothing where possibleMatch = lyingSearch f
ghci> search (\x -> x*x == 16) -- lyingSearch Just (Succ (Succ (Succ (Succ Zero)))) ghci> search (\x -> x*x == 15) Nothing
search
function correctly determined that there is no natural number with a square equal to fifteen.lyingSearch
(which is always a valid value of type Nat
), we simply feed it to the function f
and check the return value. If the required number exists, then (as has already been clarified earlier) possibleMatch
is just this number, and therefore the check will pass successfully. Otherwise, because f
ends for any input value, we get False
and return Nothing
.search
function actually works for any predicate (function Nat->Bool
), and ends in a finite time (of course, provided that f
also completes for any value of type Nat
). However, the termination condition f
for any argument passed is very strong, and it is this that strongly limits the set of admissible predicates: for example, if fx = x*x + 1 == x
will be an infinite loop. It would seem that there is not so, because such a function is completed for any number? It turns out that for anyone except for the already mentioned infinity: left and right of the equals sign will be infinitely nested Succ (Succ (Succ (...
, and accordingly it will be impossible to determine whether the left and right parts are equal. For this reason it is impossible to use this function for create a similar type for Integer
.f
completes at the infinity transmitted to it, that is, the sequence Succ (Succ (Succ (...
, it means that in any case it uses (opens) no more than some fixed number of Succ
constructors.search
for other types. A relatively simple example is also the real numbers, each represented as an endless list of numbers (see Seemingly Impossible Functional Programs ). On hackage there is a general infinite-search package that provides the corresponding monad and related functions.Source: https://habr.com/ru/post/201446/
All Articles