Professional Documents
Culture Documents
Cofree Will Tear Us Apart - Murat Kasimov
Cofree Will Tear Us Apart - Murat Kasimov
Cofree Will Tear Us Apart - Murat Kasimov
5 minute read
Published: May 31, 2018
Recently I’ve been working on distributed systems and I often need to deal with the data that
may be located anywhere. We’ll see how just one algebraic construction helped to describe a
problem with recycling data in general and then to solve it.
I’ve created a library apart, whose definitions are used in this post.
Introduction and motivation
Let’s suppose you need to write a program that works with some data. If the data is too big,
you should think about how to manage and store it because keeping it in RAM is too
dangerous, so we need to split the data into the segment that we need right now and the rest
that we don’t.
How we’re going to do that? First of all, we need an abstraction that allows us to describe
various data structures algebraically. And such an abstraction exists!
Basic construction Cofree
Many Haskellers know type, but Free Cofree is unfairly bypassed. The difference is really small
‑ while is a sum of and
Free a t (Free t a) Cofree , is a product:
Free t a = a + t (Free t a)
Cofree t a = a * t (Cofree t a)
If we pick as a basic construction, we’ll get those functions for free:
Cofree
So, how are we going to build various data structures using ? All we need is a . To Cofree Functor
be more precise, we need to instantiate type in . t Cofree t a
Suppose we need a stack or non‑empty list ‑ fairly simple structure. We can take , cause Maybe
it has everything we need: lets you continue describing a structure and
Just lets you Nothing
terminate an expression (cause it’s a null constructor).
type Stack = Cofree Maybe
https://iokasimov.github.io/posts/2018/05/cofree-will-tear-us-apart 1/4
4/21/2019 Cofree will tear us apart - Murat Kasimov
Helper construction Shape
Okay, now we know how to describe structures algebraically via . But we talked about Cofree
separation of data that is located in different places. So we’ll just add one more construction:
data Shape t raw value = Ready (t value) | Converted raw
3 10
1 6 14
4 7 13
https://iokasimov.github.io/posts/2018/05/cofree-will-tear-us-apart 2/4
4/21/2019 Cofree will tear us apart - Murat Kasimov
(10 :< Greater
(14 :< Less
(13 :< End)))
Suppose we need to keep a tree in memory with height not greater than 3. We can limit it.
limit 3 do_something_with_the_rest example
I’m intentionally not focusing on how to persist the segments ‑ it’s not the goal of this post. We
We can persist an out of range segment in a file and the
function can return the filename and line number. Or we can put
do_something_with_the_rest
them in / / and return the connection parameters and keys for the saved
Redis Memcashed Tarantool
segments. It doesn’t matter.
8 :< Crotch
(3 :< Crotch
(1 :< {RESTORE_INFO})
(6 :< {RESTORE_INFO}))
(10 :< Greater
(14 :< {RESTORE_INFO}))
So we cut off our tree and put information for restoring where these unnecessary segments
were. With we can put the whole structure back in memory.
recover
Or, we can traverse with effects on a scattered data structure and restore all the segments by
applying this function to them as well ‑ just use . fluent
Conclusion
So far, I’ve successfully defined acyclic oriented
, , , , and trees, as well as some functions to deal with them.
graphs binary prefix rose AVL Splay
The idea of using as base construction for another structures was captured from the
Cofree
description module in package of Edward Kmett.
Control.Comonad.Cofree free
https://iokasimov.github.io/posts/2018/05/cofree-will-tear-us-apart 3/4
4/21/2019 Cofree will tear us apart - Murat Kasimov
https://iokasimov.github.io/posts/2018/05/cofree-will-tear-us-apart 4/4