Generator/Exponential: Difference between revisions

→‎{{header|Python}}: Added a version showing the compositional derivation of custom generators.
(→‎{{header|Haskell}}: Added type signatures, dropped a redundant $)
(→‎{{header|Python}}: Added a version showing the compositional derivation of custom generators.)
Line 2,360:
 
{{out}}
<pre>[529, 576, 625, 676, 784, 841, 900, 961, 1024, 1089]</pre>
 
 
Or, deriving custom generators compositionally:
 
<lang python>'''Exponentials as generators'''
 
from itertools import count, islice
 
 
# powers :: Gen [Int]
def powers(n):
'''A non-finite succession of integers,
starting at zero,
raised to the nth power.'''
 
return fmapGen(flip(curry(pow))(n))(
count(0)
)
 
 
# main :: IO ()
def main():
'''Taking the difference between two derived generators.'''
 
print(
take(10)(
drop(20)(
differenceGen(powers(2))(
powers(3)
)
)
)
)
 
 
# GENERIC -------------------------------------------------
 
 
# curry :: ((a, b) -> c) -> a -> b -> c
def curry(f):
'''A curried function derived
from an uncurried function.'''
return lambda a: lambda b: f(a, b)
 
 
# differenceGen :: Gen [a] -> Gen [a] -> Gen [a]
def differenceGen(ga):
'''All values of ga except any
already seen in gb.'''
def go(a, b):
stream = zip(a, b)
bs = set([])
while True:
xy = next(stream, None)
if None is not xy:
x, y = xy
bs.add(y)
if x not in bs:
yield x
else:
return
return lambda gb: go(ga, gb)
 
 
# drop :: Int -> [a] -> [a]
# drop :: Int -> String -> String
def drop(n):
'''The sublist of xs beginning at
(zero-based) index n.'''
def go(xs):
if isinstance(xs, list):
return xs[n:]
else:
take(n)(xs)
return xs
return lambda xs: go(xs)
 
 
# flip :: (a -> b -> c) -> b -> a -> c
def flip(f):
'''The curried function f with its
arguments reversed.'''
return lambda a: lambda b: f(b)(a)
 
 
# fmapGen <$> :: (a -> b) -> Gen [a] -> Gen [b]
def fmapGen(f):
'''A function f mapped over a
non finite stream of values.'''
def go(g):
while True:
v = next(g, None)
if None is not v:
yield f(v)
else:
return
return lambda gen: go(gen)
 
 
# take :: Int -> [a] -> [a]
# take :: Int -> String -> String
def take(n):
'''The prefix of xs of length n,
or xs itself if n > length xs.'''
return lambda xs: (
xs[0:n]
if isinstance(xs, list)
else list(islice(xs, n))
)
 
 
# MAIN ---
if __name__ == '__main__':
main()</lang>
{{Out}}
<pre>[529, 576, 625, 676, 784, 841, 900, 961, 1024, 1089]</pre>
 
9,659

edits