Rolling Your Own Blockchain in Haskell

(michaelburge.us)

234 points | by nicolast 2439 days ago

7 comments

  • lambdaxdotx 2439 days ago
    Here is another "minimum viable" blockchain implementation in Haskell: https://github.com/adjoint-io/nanochain.

    It's a bit simpler in implementation; the relevant data structures are defined a bit differently, so it could give a nice alternate perspective about what a blockchain written in Haskell may look like.

  • qaezel 2439 days ago
  • umen 2439 days ago
    Great stuff , where can I learn about blackchain in begginers level with code examples ?
  • ngcc_hk 2439 days ago
    any other language? Python and lisp would be interesting.
  • alphaalpha101 2439 days ago
    I like the idea behind this article, but this isn't the way to do it. It hides the simplicity of the blockchain concept behind arcane syntax and overly complicated higher-order typing constructs.

        newtype BlockF a = Block (V.Vector a) deriving (Eq, Show, Foldable, Traversable, Functor, Monoid)
        type Block = BlockF Transaction
    
        type Blockchain = Cofree MerkleF Block
    
    Does anyone really think this is how one should write software? I think that constructions like Cofree are interesting, but I don't think they're programming.
    • thinkpad20 2439 days ago
      I agree and disagree. There is nothing about the usage of Cofree and other similar concepts which is "not programming". I think it's a completely viable way to write software within a particular scope (e.g. depending on the team that will work with the internals of the code, and whether the users of the library are to be required to understand the concept). If it provides the correct abstraction and can lead to more performant, maintainable and/or readable code (which is of course subjective), then by all means.

      That said, I agree that the article doesn't spend a great deal of time explaining the concepts, whether blockchain itself or the category theory it's using, leading to a sense (for me) of being overly terse and coming across as a bit pompous. Although, I realize that for a certain audience there's nothing pompous about this at all and it might seem perfectly reasonable.

      • jcranberry 2439 days ago
        Coming from a math background, this actually reads as very expository and not at all pompous.
        • alphaalpha101 2438 days ago
          Coming from a maths background, it's not expository. It's pompous. Referring to the original article, btw.
          • voidz 2437 days ago
            Coming from the Internet, how about you both back up your statement with some rationale?
          • jcranberry 2437 days ago
            I really don't see how you can think this is pompous or terse after reading math textbooks.
            • alphaalpha101 2437 days ago
              Maths textbooks contain real mathematics and are aimed at mathematicians or mathematics students.

              This is about a blockchain, and is presented using Haskell and over-the-top Haskell pseudo-category-theory.. it just doesn't compute for me.

    • WmyEE0UsWAwC2i 2439 days ago
      It depends on the reader's amount of "vocabulary". Why write more complicated code if it is just Cofree? DRY.

      OTOH, how many elements should the reader's vocabulary have to enable him to read other's people code?

      • mixedCase 2439 days ago
        From https://hackage.haskell.org/package/free-4.12.4/docs/Control... :

        "A Comonad v is a cofree Comonad for f if every comonad homomorphism from another comonad w to v is equivalent to a natural transformation from w to f.

        A cofree functor is right adjoint to a forgetful functor.

        Cofree is a functor from the category of functors to the category of comonads that is right adjoint to the forgetful functor from the category of comonads to the category of functors that forgets how to extract and duplicate, leaving you with only a Functor."

        So I take it you believe that a degree in category theory is the bare minimum for people to expect to be able to understand other people's code? The layman interpretation of "Avoid success at all costs" comes to mind.

        • phillipcarter 2439 days ago
          Although I don't disagree regarding the difficulty of understanding Cofree, at least the blog post explains what it's doing in this context. That alone was enough for me to understand that beginning snippet, convince me that there was at least some utility in the use of Cofree here, and remember this as an example of where it can be useful.

          The parent^2 comment also snipped an example explained in the blog post, where he specifically chose that structure so that he could make use of built-in structures to traverse the tree. Similar to the use of Cofree (though I understand the Traversable monad far more), the reasoning was presented, it made sense, and I could move on from that without scratching my head.

        • wyager 2439 days ago
          You don't need to understand category theory to understand Cofree. It's not a very complicated construction. The Haskell ecosystem's provision of stuff like Free, Cofree, Fix, etc. covers a huge number of common constructions and saves you a lot of effort.

          A common example of a "kind of hard problem" I see all the time on various tech sites (e.g. here) is flattening a rose tree (arbitrary depth nested array). Guess what? In Haskell, you can express the whole structure as "Free []". Hundreds of useful primitives are already written for you, including the thing you need to flatten the tree, "toList". This just goes to show that it's not a pointless masturbatory excercise in dragging math into software engineering; it's actually directly and immediately very useful.

          • reikonomusha 2439 days ago
            Someone not understanding how to flatten a tree (or what have you) to having to understand Free is a huge jump.
        • nilkn 2439 days ago
          I think this is more a failure of documentation than anything else. The definition provided there is correct and useful for a certain subset of people, but there are ways of grokking comonads and cofree comonads that don't require so much math.

          It's a tricky concept no matter how you slice it (in my opinion), but I like the following article:

          http://dlaing.org/cofun/posts/free_and_cofree.html

          I won't claim it's easy reading, but it's a lot more grounded and motivated.

        • WmyEE0UsWAwC2i 2439 days ago
          I belive that abstraction can be a double edged sword.

          Pro. you write less code Pro. Your code is easier to read for everyone familiar with the abstraction. Con. You need a math degree. Con. Harder to get contributors. etc...

          Tangentially. The docs also say that:

          "In practice, cofree comonads are quite useful for annotating syntax trees, or talking about streams."

          Sometimes you can learn the abstraction and one of its particualr use cases. And apply it when you find it, without needing the degree.

          Also to answer your question: "So I take it you believe that a degree in category theory is the bare minimum for people to expect to be able to understand other people's code?"

          No, I don't believe so.

          But the experiment of forming a team of people that knows all this to see how productive they are, would be nice to see.

        • catnaroek 2439 days ago
          This kind of language sounds intimidating if you aren't familiar with it, but it's actually not that complicated. The documentation states the universal property of the cofree comonad for a functor. You don't need a degree in math to understand it - the bits of category theory that most Haskellers use are very basic.
    • MichaelBurge 2439 days ago
      Cofree in general I use all the time, especially in compilers. The Generic and Binary Cofree instances were lifted straight out of a decompiler I'm supposed to be working on. The most common reason is to get Traversable and Plated instances:

      https://hackage.haskell.org/package/lens-4.15.4/docs/Control...

      For the blockchain stuff specifically, I suppose I didn't really use them too heavily in this article. So you could argue they aren't currently doing a whole lot of good.

      I'm not actually certain if people prefer seeing the heavier types that I default to in real code(to avoid refactoring later), vs. types that are as simple as needed but might need to change as the program evolves. The first choice lets people who already know Haskell learn something from it, while the second makes beginners less confused.

      • pseudonom- 2437 days ago
        Actually, I realized I follow the "abstract recursion out of your structures" intuition but don't really realize why you chose Cofree instead of some of the other options:

            import Control.Monad.Free
            import Control.Comonad.Cofree
            import Data.Functor.Foldable
        
            data A f
              = ANil
              | ACons f
            type AList a = Cofree A a
            a :: AList Int
            a = 1 :< ACons (2 :< ACons (3 :< ANil))
            
            data B a f
              = B a f
            type BList a = Free (B a) ()
            b :: BList Int
            b = Free (B 1 (Free (B 2 (Free (B 3 (Pure ()))))))
            
            data C a f
              = CCons a f
              | CNil
            type CList a = Fix (C a)
            c :: CList Int
            c = Fix (CCons 1 (Fix (CCons 2 (Fix (CCons 3 (Fix CNil))))))
        
        You wanted to ensure it's non-empty? Something about the actual Comonad (extend, etc) interface?
      • pseudonom- 2439 days ago
        FWIW, I appreciated the example of Cofree in use.
    • rev_null 2439 days ago
      I think the opposite could be said. That the C++ implementation hides the simplicity of the blockchain in a language that lacks powerful abstractions and prevents code reuse.

      If cofree seems like it isn't programming, that is only because this style of code helps avoid the need for it.

  • macsj200 2439 days ago
    Initially read submission site as malbolge.us
  • cyphar 2439 days ago
    It's quite a cute idea, implementing a blockchain (a fundamentally impure concept) in Haskell. If you're interested in other cool Haskell projects, check out JoeyH[1].

    [1]: http://joeyh.name/code/

    • arianvanp 2439 days ago
      Seems a fundamentally pure concept to me. Writing down facts that never change in append-only fashion.
    • Kinnard 2439 days ago
      What do you mean by a 'fundamentally impure concept'?
      • quickthrower2 2439 days ago
        Not the OP but maybe he means there are side effects. Of course Haskell can side effects that is one of the big misconceptions.
      • cyphar 2439 days ago
        Impure as in "has side-effects". An append-only state that is used for synchronisation between different machines by definition has side-effects. Of course, you can have side-effects in Haskell, I just thought it was an interesting choice.
        • tree_of_item 2439 days ago
          Haskell takes a stand against implicit side-effects, letting you see what a function is capable of doing in its type. It's really weird to suggest that performing side-effects in such a language is strange or awkward or cute or whatever. Doing those things is the whole point of writing programs.