View difference between Paste ID: QS7b2N8Q and KMUtKuMJ
SHOW: | | - or go back to the newest paste.
1
#!/usr/bin/env python
2
3
4
# -- File "seemingly-impossible.hs",
5
# -- automatically extracted from literate Haskell
6
# -- file http://www.cs.bham.ac.uk/~mhe/papers/seemingly-impossible.html
7
# --
8
# -- Martin Escardo, September 2007
9
# -- School of Computer Science, University of Birmingham, UK
10
# --
11
# -- These algorithms have been published and hence are in the
12
# -- public domain.
13
# --
14
# -- If you use them, I'd like to know! mailto:m.escardo@cs.bham.ac.uk
15
#
16
# infix hack:
17
# https://code.activestate.com/recipes/384122/
18
class Infix:
19
    def __init__(self, function):
20
        self.function = function
21
    def __ror__(self, other):
22
        return Infix(lambda x, self=self, other=other: self.function(other,
23
x))
24
    def __or__(self, other):
25
        return self.function(other)
26
    def __rlshift__(self, other):
27
        return Infix(lambda x, self=self, other=other: self.function(other,
28
x))
29
    def __rshift__(self, other):
30
        return self.function(other)
31
    def __call__(self, value1, value2):
32
        return self.function(value1, value2)
33
34
35
def ifthen(test, trueF, falseF):
36
 if (test):
37
   return trueF()
38
 else:
39
   return falseF()
40
 
41
# data Bit = Zero | One
42
#          deriving (Eq)
43
44
# Don't bother with a dedicated type or coerce, just define some constants
45
zero = 0
46
one = 1
47
48
49
# type Natural = Integer
50
# type Cantor = Natural -> Bit
51
# (#) :: Bit -> Cantor -> Cantor 
52
53
# x # a = lambda i: if i == 0 then x else a(i-1)
54-
q = Infix ( lambda x, a: (lambda i: ifThen ((i ==0), (lambda: x), (lambda: a(i-1)))))
54+
def q(x,a): return (lambda i: ifthen ((i ==0), (lambda: x), (lambda: a(i-1))))
55
56
# forsome, forevery :: (Cantor -> Bool) -> Bool
57
# find :: (Cantor -> Bool) -> Cantor
58
# find = find_i
59-
find = lambda p: find_i(p)
59+
60
# find_i :: (Cantor -> Bool) -> Cantor
61
# find_i p = if forsome(lambda a: p(Zero # a))
62
#            then Zero # find_i(lambda a: p(Zero # a))
63
#            else One  # find_i(lambda a: p(One  # a))
64
# search :: (Cantor -> Bool) -> Maybe Cantor
65
66
# forevery p = not(forsome(lambda a: not(p a)))
67
def forevery(p): return (not (forsome( lambda a: not (p (a)))))
68-
def forevery(p): not (forsome( lambda a: not (p (a))))
68+
69
# forsome p = p(find(lambda a: p(a)))
70
def forsome(p): return (p(find_ii(lambda a: p(a))))
71-
def forsome(p): p(find_i(lambda a: p(a)))
71+
72
def find_ii(p): return (lambda j: ifthen (p(q (zero, find_ii (lambda a: p(q(zero, a)))))
73-
def find_i (p):
73+
         ,lambda : q(zero, find_ii(lambda a: p(q(zero, a))))(j)
74-
  if forsome (lambda a: p(zero |q| a)):
74+
         ,lambda : q(one, find_ii(lambda a: p(q(one, a))))(j)))
75-
    return zero |q| find_i(lambda a: p( zero |q| a))   
75+
76
# search p = if forsome(lambda a: p(a)) then Just(find(lambda a: p(a))) else Nothing
77-
    return one  |q| find_i(lambda a: p( one  |q| a))   
77+
78
 if forsome(lambda a : p(a)):
79
   find(lambda a: p(a)) 
80
 else: None
81
82
# equal :: Eq y => (Cantor -> y) -> (Cantor -> y) -> Bool
83
# equal f g = forevery(lambda a: f(a) == g(a))
84
def equal(f, g): return (forevery(lambda a: f(a) == g(a)))
85
86
# coerce :: Bit -> Natural
87-
def equal(f, g): forevery(lambda a: f(a) == g(a))
87+
88
# coerce One = 1
89
coerce = lambda x: x
90
91
# f, g, h :: Cantor -> Integer
92
f = lambda a: coerce(a(2 * coerce(a(4)) +  4 * (coerce(a(5)))))
93
g = lambda a: coerce(a(coerce(a(4)) + 4 * (coerce(a(5)))))
94
def h(a):
95-
f = lambda a: coerce(a(7 * coerce(a(4)) +  4 * (coerce(a(7))) + 4))
95+
      if a(5) == zero:
96-
g = lambda a: coerce(a(coerce(a(4)) + 11 * (coerce(a(7)))))
96+
97
           return (coerce(a(0)))
98-
      if a(7) == zero:
98+
99
           return (coerce(a(2)))
100-
           coerce(a(4))
100+
101
           if a(4) == one:
102-
           coerce(a( 11))
102+
             return (coerce(a(6) ))
103
           else:
104
             return (coerce(a(4)))
105-
             coerce(a( 15) )
105+
106
# modulus :: (Cantor -> Integer) -> Natural
107-
             coerce(a(8))
107+
108
def modulus (f): return (least(lambda n: forevery(lambda a: forevery(lambda b: (not (eq(n, a, b))) or (f(a) == f( b))))))
109
110
# least :: (Natural -> Bool) -> Natural
111-
def modulus (f):  least(lambda n: forevery(lambda a: forevery(lambda b: (not (eq(n, a, b))) or (f(a) == f( b)))))
111+
112
  if p(0): 
113
   return 0
114
  else:
115
   return (1 + least(lambda n: p(n+1)))
116-
   x=0
116+
117
# eq :: Natural -> Cantor -> Cantor -> Bool
118-
   x=1
118+
119-
  x + least(lambda n: p(n+1))
119+
120
    return True
121
  else:
122
   return (a(n-1) == b (n-1)) and (eq(n-1,a,b))
123
124
# proj :: Natural -> (Cantor -> Integer)
125
def proj(i): return (lambda a: coerce(a(i)))
126-
   return (a(n-1) == b (n-1)) and (eq(n,a,b))
126+
127
128
# find_ii p = if p(Zero # find_ii(lambda a: p(Zero # a)))
129-
def proj(i): lambda a: coerce(a(i))
129+
130
#             else One  # find_ii(lambda a: p(One  # a))
131
# find_iii :: (Cantor -> Bool) -> Cantor
132
# find_iii p = h # find_iii(lambda a: p(h # a))
133
#        where h = if p(Zero # find_iii(lambda a: p(Zero # a))) then Zero else
134
#        One
135
# find_iv :: (Cantor -> Bool) -> Cantor
136
# find_iv p = let leftbranch = Zero # find_iv(lambda a: p(Zero # a))
137
#             in if p(leftbranch)
138
#                then leftbranch
139
#                else One # find_iv(lambda a: p(One # a))
140
# find_v :: (Cantor -> Bool) -> Cantor
141
# find_v p = lambda n:  if q n (find_v(q n)) then Zero else One
142
#  where q n a = p(lambda i: if i < n then find_v p i else if i == n then Zero
143
#  else a(i-n-1))
144
# find_vi :: (Cantor -> Bool) -> Cantor
145
# find_vi p = b 
146
#  where b = lambda n: if q n (find_vi(q n)) then Zero else One
147
#        q n a = p(lambda i: if i < n then b i else if i == n then Zero else
148
#        a(i-n-1))
149
# find_vii :: (Cantor -> Bool) -> Cantor
150
# find_vii p = b 
151
#  where b = id'(lambda n: if q n (find_vii(q n)) then Zero else One)
152
#        q n a = p(lambda i: if i < n then b i else if i == n then Zero else
153
#        a(i-n-1))
154
155
# data T x = B x (T x) (T x)
156
# code :: (Natural -> x) -> T x
157
# code f = B (f 0) (code(lambda n: f(2*n+1))) 
158
#                  (code(lambda n: f(2*n+2)))
159
# decode :: T x -> (Natural -> x)
160
# decode (B x l r) n |  n == 0    = x
161
#                    |  odd n     = decode l ((n-1) `div` 2)
162
#                    |  otherwise = decode r ((n-2) `div` 2)
163
# id' :: (Natural -> x) -> (Natural -> x)
164
# id' = decode.code
165
# f',g',h' :: Cantor -> Integer
166
# f' a = a'(10*a'(3^80)+100*a'(4^80)+1000*a'(5^80)) where a' i = coerce(a
167
# i)
168
# g' a = a'(10*a'(3^80)+100*a'(4^80)+1000*a'(6^80)) where a' i = coerce(a
169
# i)
170
# h' a = a' k 
171
#     where i = if a'(5^80) == 0 then 0    else 1000
172
#           j = if a'(3^80) == 1 then 10+i else i
173
#           k = if a'(4^80) == 0 then j    else 100+j 
174
#           a' i = coerce(a i)
175
176
# pointwiseand :: [Natural] -> (Cantor -> Bool)
177
# pointwiseand [] = lambda b: True
178
# FIXME how to emulate pattern match (n:a)
179
def  pointwiseand (ns):
180
  if (ns == []):
181
    return True
182
  else:
183
    return (lambda b: (b(ns[0]) == one) and pointwiseand(ns[0], b))
184
185
# sameelements :: [Natural] -> [Natural] -> Bool
186
sameelements = lambda a, b:  equal (pointwiseand(a), pointwiseand(b))
187
188
print modulus(proj(1))
189
print equal(h,h)
190
print equal(h,g)
191
print equal(h,f)