TakeS this Stream and ... it!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
module Data.Stream where

import Data.Peano           -- http://lpaste.net/107204
import Control.Comonad      -- http://lpaste.net/107661
import Control.Monad

infixr 5 :<

-- http://lpaste.net/107665

-- This is a solution to the bonus Haskell question 
-- at http://lpaste.net/107655

-- a stream is a ... well, stream of objects, usually defined by some
-- unfold-like function ('unfold' function can also be considered a kind
-- of a continuation ... but can't everything, then? Even not-continued
-- functions have a continuation: it's called 'stop.' ;)

data Stream a = a :< Stream a

instance Show a => Show (Stream a) where
   show stream@(a :< as) = "Stream" ++ showSome 5 stream

showSome :: Show a => Int -> Stream a -> String
showSome x stream = "{ " ++ s' (fromInt x) stream ++ "... }"
   where s' Z _ = ""
         s' (S n) (a :< as) = show a ++ " :< " ++ s' n as

instance Copointed Stream where
   extract (a :< _) = a

instance Functor Stream where
   fmap f (a :< as) = f a :< fmap f as

instance Comonad Stream where
   duplicate stream@(a :< as) = stream :< duplicate as

-- a chooser function to pick some element from the stream:

choose :: Stream a -> [(a, Stream a)]
choose (a :< as) = (a, as) : choose as

-- So, a stream of 2-4-2 numbers that are primes-...ish are:

torf :: Integer -> Integer
torf x = (6 - x) -- given that x is either 2 or 4

primesish :: Stream Integer
primesish = let seed = 7 :< 11 :< (seed =>> \(a :< b :< _) -> b + torf (b - a))
            in  2 :< 3 :< 5 :< seed

nats :: Stream Integer
nats = 0 :< (nats =>> succ . extract)

fibs :: Integral a => Stream a
fibs = 0 :< 1 :< (fibs =>> \(a :< b :< _) -> a + b)

one :: Stream Double
one = 0.5 :< (one =>> (0.5 *) . extract)

oneThird :: Stream Double
oneThird = 0.5 :< (oneThird =>> ((-0.5) *) . extract)

takeS :: Int -> Stream a -> [a]
takeS n stream = t' (fromInt n) stream
   where t' Z _ = []
         t' (S n) (a :< as) = a : t' n as

dropS :: Int -> Stream a -> Stream a
dropS n stream = d' (fromInt n) stream
   where d' Z s = s
         d' (S n) (_ :< as) = d' n as

takeWhileS :: (a -> Bool) -> Stream a -> [a]
takeWhileS pred (a :< as) | pred a = a : takeWhileS pred as
                          | otherwise = []

dropWhileS :: (a -> Bool) -> Stream a -> Stream a
dropWhileS pred stream@(a :< as) | pred a = dropWhileS pred as
                                 | otherwise = stream

filterS :: (a -> Bool) -> Stream a -> Stream a
filterS pred (a :< as) | pred a = a :< filterS pred as
                       | otherwise = filterS pred as

tailS :: Stream a -> Stream a
tailS (_ :< as) = as

headS :: Stream a -> a
headS (a :< _) = a
46:10: Warning: Redundant bracket
Found:
(6 - x)
Why not:
6 - x
65:1: Error: Eta reduce
Found:
takeS n stream = t' (fromInt n) stream
Why not:
takeS n = t' (fromInt n)
70:1: Error: Eta reduce
Found:
dropS n stream = d' (fromInt n) stream
Why not:
dropS n = d' (fromInt n)