| Safe Haskell | Safe-Inferred |
|---|---|
| Language | Haskell2010 |
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
- data Bit
- _O :: Prism' Bit ()
- _I :: Prism' Bit ()
- _O' :: ExhaustivePrism Bit (o, i) (o', i) () o o'
- _I' :: ExhaustivePrism Bit (o, i) (o, i') () i i'
- type Binary = [Bit]
- zeroo :: Term Binary -> Goal ()
- poso :: Term Binary -> Goal ()
- gtlo :: Term Binary -> Goal ()
- binaryo :: Term Binary -> Goal ()
- addo :: Term Binary -> Term Binary -> Term Binary -> Goal ()
- subo :: Term Binary -> Term Binary -> Term Binary -> Goal ()
- lesso :: Term Binary -> Term Binary -> Goal ()
- mulo :: Term Binary -> Term Binary -> Term Binary -> Goal ()
- divo :: Term Binary -> Term Binary -> Term Binary -> Term Binary -> Goal ()
- logo :: Term Binary -> Term Binary -> Term Binary -> Term Binary -> Goal ()
- example :: IO ()
Documentation
_O' :: ExhaustivePrism Bit (o, i) (o', i) () o o' Source #
_I' :: ExhaustivePrism Bit (o, i) (o, i') () i i' Source #
gtlo :: Term Binary -> Goal () Source #
Check that the number is greater than one (i.e. at least two).
The naming comes from the paper.
Arguments
| :: Term Binary |
|
| -> Term Binary |
|
| -> Term Binary |
|
| -> 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.
Arguments
| :: Term Binary |
|
| -> Term Binary |
|
| -> Term Binary |
|
| -> Goal () |
Calculate the difference c of two numbers a and b. This is just
addo, but with parameters in different order.
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]]
Arguments
| :: Term Binary |
|
| -> Term Binary |
|
| -> Term Binary |
|
| -> 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.
Arguments
| :: Term Binary |
|
| -> Term Binary |
|
| -> Term Binary |
|
| -> Term Binary |
|
| -> 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.
Arguments
| :: Term Binary |
|
| -> Term Binary |
|
| -> Term Binary |
|
| -> Term Binary |
|
| -> 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.