Skip to content

Instantly share code, notes, and snippets.

@xgrommx
Forked from sellout/metamorphism.hs
Created March 15, 2018 17:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xgrommx/6721ec537390a18b07b2923e51e5d705 to your computer and use it in GitHub Desktop.
Save xgrommx/6721ec537390a18b07b2923e51e5d705 to your computer and use it in GitHub Desktop.
Trying to generalize [metamorphisms](http://www.cs.ox.ac.uk/jeremy.gibbons/publications/metamorphisms-scp.pdf) away from lists.
-- | A “flushing” 'stream', with an additional coalgebra for flushing the
-- remaining values after the input has been consumed. This also allows us to
-- generalize the output away from lists.
fstream
:: (Cursive t (XNor a), Cursive u f, Corecursive u f, Traversable f)
=> Coalgebra f b -> (b -> a -> b) -> Coalgebra f b -> b -> t -> u
fstream ψ g ψ' = go
where
go c x =
let fb = ψ c
in if 0 < length fb
then embed $ fmap (flip go x) fb
else case project x of
Both a x' -> go (g c a) x'
None -> ana ψ' c
-- | Like 'fstream', but rather than using the 'length' of the 'f' from the
-- 'Coalgebra', we use a 'CoalgebraM' (but this makes it impossible to write
-- 'afstream''). It also reduces the 'Traversable' constraint to 'Functor'.
-- The 'CoalgebraM' also allows us to distinguish between cases where we just
-- want to stop processing input ('Just None') and the case when we need to
-- acquire more input ('Nothing'), which becomes more interesting when 'u'
-- isn’t a list and may have multiple leaf nodes.
fstream'
:: (Cursive t (XNor a), Cursive u f, Corecursive u f, Functor f)
=> CoalgebraM Maybe f b -> (b -> a -> b) -> Coalgebra f b -> b -> t -> u
fstream' ψ g ψ' = go
where
go c x =
maybe (case project x of
Both a x' -> go (g c a) x'
None -> ana ψ' c)
(embed . fmap (flip go x))
$ ψ c
-- | An “auto-flushing” stream – uses the same coalgebra for streaming
-- generation and flushing. It gives us the original signature of 'stream',
-- but still generalized away from lists.
afstream
:: (Cursive t (XNor a), Cursive u f, Corecursive u f, Traversable f)
=> Coalgebra f b -> (b -> a -> b) -> b -> t -> u
afstream ψ g = fstream ψ g ψ
-- | A stream for truly infinite inputs.
sstream
:: (Cursive t ((,) a), Cursive u f, Traversable f)
=> Coalgebra f b -> (b -> a -> b) -> b -> t -> u
sstream ψ g = go
where
go c x =
let fb = ψ c
in if 0 < length fb
then embed $ fmap (flip go x) fb
else case project x of
(a, x') -> go (g c a) x'
-- | This is to 'sstream' as 'fstream'' is to 'fstream'.
sstream'
:: (Cursive t ((,) a), Cursive u f, Functor f)
=> CoalgebraM Maybe f b -> (b -> a -> b) -> b -> t -> u
sstream' ψ g = go
where
go c x =
maybe (case project x of (a, x') -> go (g c a) x')
(embed . fmap (flip go x))
$ ψ c
-- | Streaming representation-changers – a.k.a., metamorphism.
stream :: Coalgebra (XNor c) b -> (b -> a -> b) -> b -> [a] -> [c]
stream ψ g = fstream ψ g (const None)
snoc :: [a] -> a -> [a]
snoc x a = x ++ [a]
x :: [Int]
x = stream project snoc [] [1, 2, 3, 4, 5]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment