typedKanren-0.1.0.0
Safe HaskellSafe-Inferred
LanguageHaskell2010

Kanren.Data.Binary

Description

This module implements binary numbers as described in the declarative pearl “Pure, Declarative, and Constructive Arithmetic Relations” by O. Kiselyov et al.

The paper is available at https://okmij.org/ftp/Prolog/Arithm/arithm.pdf and the original implementation in Prolog is available at https://okmij.org/ftp/Prolog/Arithm/pure-bin-arithm.prl.

Synopsis

Documentation

data Bit Source #

Constructors

O 
I 

Instances

Instances details
Generic Bit Source # 
Instance details

Defined in Kanren.Data.Binary

Associated Types

type Rep Bit :: Type -> Type #

Methods

from :: Bit -> Rep Bit x #

to :: Rep Bit x -> Bit #

Num Binary Source # 
Instance details

Defined in Kanren.Data.Binary

Show Bit Source # 
Instance details

Defined in Kanren.Data.Binary

Methods

showsPrec :: Int -> Bit -> ShowS #

show :: Bit -> String #

showList :: [Bit] -> ShowS #

NFData Bit Source # 
Instance details

Defined in Kanren.Data.Binary

Methods

rnf :: Bit -> () #

Eq Bit Source # 
Instance details

Defined in Kanren.Data.Binary

Methods

(==) :: Bit -> Bit -> Bool #

(/=) :: Bit -> Bit -> Bool #

Logical Bit Source # 
Instance details

Defined in Kanren.Data.Binary

Associated Types

type Logic Bit = (r :: Type) Source #

type Rep Bit Source # 
Instance details

Defined in Kanren.Data.Binary

type Rep Bit = D1 ('MetaData "Bit" "Kanren.Data.Binary" "typedKanren-0.1.0.0-DCPxkt07imEEe1U3d5R120" 'False) (C1 ('MetaCons "O" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "I" 'PrefixI 'False) (U1 :: Type -> Type))
type Logic Bit Source # 
Instance details

Defined in Kanren.Data.Binary

type Logic Bit = Bit

_O' :: ExhaustivePrism Bit (o, i) (o', i) () o o' Source #

_I' :: ExhaustivePrism Bit (o, i) (o, i') () i i' Source #

type Binary = [Bit] Source #

zeroo :: Term Binary -> Goal () Source #

Check that the number is zero.

poso :: Term Binary -> Goal () Source #

Check that the number is positive, i.e. greater than zero.

gtlo :: Term Binary -> Goal () Source #

Check that the number is greater than one (i.e. at least two).

The naming comes from the paper.

binaryo :: Term Binary -> Goal () Source #

Generate valid binary numbers.

addo Source #

Arguments

:: Term Binary

a, the first summand

-> Term Binary

b, the second summand

-> Term Binary

c, the sum

-> Goal () 

Calculate the sum c of two numbers a and b.

>>> extract' <$> run (addo (inject' 3) (inject' 5))
[Just [O,O,O,I]]

One can turn it around to subtract from a number:

>>> extract' <$> run (\b -> addo (inject' 2) b (inject' 8))
[Just [O,I,I]]

When both summands are unknown, every possible pair will be enumerated.

>>> bimap extract' extract' <$> run (\(a, b) -> addo a b (inject' 2))
[(Just [O,I],Just []),(Just [],Just [O,I]),(Just [I],Just [I])]

If one of the summands is greater than the sum, the relation will produce no results.

>>> run (\a -> addo a (inject' 10) (inject' 3))
[]

The implementation of add is discussed in section 4 of the paper.

subo Source #

Arguments

:: Term Binary

a, the minuend

-> Term Binary

b, the subtrahend

-> Term Binary

c, the difference

-> Goal () 

Calculate the difference c of two numbers a and b. This is just addo, but with parameters in different order.

lesso Source #

Arguments

:: Term Binary

a, the lesser number

-> Term Binary

b, the greater number

-> Goal () 

Check that a is strictly less than b. Otherwise, the goal fails.

>>> run (\() -> lesso (inject' 3) (inject' 4))
[()]
>>> run (\() -> lesso (inject' 3) (inject' 2))
[]

One can turn this relation around to generate numbers less or greater than a given one.

>>> extract' <$> run (\x -> lesso x (inject' 4))
[Just [],Just [I],Just [I,I],Just [O,I]]
>>> take 5 $ extract' <$> run (\x -> lesso (inject' 4) x)
[Just [I,O,I],Just [O,I,I],Just [I,I,I],Just [O,O,O,I],Just [I,O,O,I]]

mulo Source #

Arguments

:: Term Binary

a, the first multiplier

-> Term Binary

b, the second multiplier

-> Term Binary

c, the product

-> Goal () 

Calculate the product c of two numbers a and b.

>>> extract' <$> run (mulo (inject' 3) (inject' 4))
[Just [O,O,I,I]]

One can turn this around to factor a given number.

>>> extract' <$> run (\a -> mulo a (inject' 2) (inject' 12))
[Just [O,I,I]]
>>> bimap extract' extract' <$> run (\(a, b) -> mulo a b (inject' 4))
[(Just [I],Just [O,O,I]),(Just [O,I],Just [O,I]),(Just [O,O,I],Just [I])]

The goal will fail if any multiplier is not a factor of the product.

>>> run (\a -> mulo a (inject' 5) (inject' 7))
[]

The implementation of mul is discussed in section 5 of the paper.

divo Source #

Arguments

:: Term Binary

n, the dividend

-> Term Binary

m, the divisor

-> Term Binary

q, the quotient

-> Term Binary

r, the remainder

-> Goal () 

Calculate the quotient q and remainder r of dividing n by m.

>>> bimap extract' extract' <$> run (\(q, r) -> divo (inject' 17) (inject' 5) q r)
[(Just [I,I],Just [O,I])]

One can turn this around to find divisors of a number.

>>> extract' <$> run (\m -> fresh >>= \q -> divo (inject' 12) m q (inject' 0))
[Just [O,O,I,I],Just [I],Just [I,I],Just [O,I,I],Just [O,I],Just [O,O,I]]

The implementation of div is discussed in section 6 of the paper.

Source #

Arguments

:: Term Binary

n, of which to calculate the logarithm

-> Term Binary

b, the base

-> Term Binary

q, the logarithm

-> Term Binary

r, the remainder

-> Goal () 

Calculate discrete logarithm q of a number n in base b, perhaps with some remainder r.

>>> bimap extract' extract' <$> run (\(q, r) -> logo (inject' 9) (inject' 3) q r)
[(Just [O,I],Just [])]
>>> bimap extract' extract' <$> run (\(q, r) -> logo (inject' 15) (inject' 3) q r)
[(Just [O,I],Just [0,I,I])]

One can turn this around to find the number b raised to some power q:

>>> extract' <$> run (\n -> logo n (inject' 5) (inject' 2) (inject' 0))
[Just [I,O,O,I,I]]

or to find the q-th root of n:

>>> extract' <$> run (\b -> logo (inject' 8) b (inject' 3) (inject' 0))
[Just [O,I]]

If you want to enumerate solutions to logo n b q r, you probably shouldn't go beyond the first 16 solutions without an OOM killer.

The original implementation of this relation in Prolog can be found at https://okmij.org/ftp/Prolog/Arithm/pure-bin-arithm.prl. Although the paper mentions this relation in section 6, it does not discuss its implementation in detail.