{
  "$type": "site.standard.document",
  "bskyPostRef": {
    "cid": "bafyreiaytxcbubwyvejnyboex74coydhyf75xnis3tebm2pljamjbbruqy",
    "uri": "at://did:plc:pi6woz4d47bkuws673w2il2r/app.bsky.feed.post/3mkt5kwylnkb2"
  },
  "path": "/t/free-like-data-structure/14012#post_9",
  "publishedAt": "2026-05-01T21:29:01.000Z",
  "site": "https://discourse.haskell.org",
  "tags": [
    "gist.github.com",
    "https://gist.github.com/LiamGoodacre/89a6de441a158dd5f8abe890604d3aff",
    "show original"
  ],
  "textContent": "Here’s some playing around in a gist (I called it `Gree`).\n\nIt shows that to come from regular Free / have a Monad instance: you need to be able to peek under layers.\n\ngist.github.com\n\n#### https://gist.github.com/LiamGoodacre/89a6de441a158dd5f8abe890604d3aff\n\n##### Main.hs\n\n\n    {-# OPTIONS_GHC -Wall #-}\n    {-# LANGUAGE GADTs, BlockArguments, LambdaCase, DerivingStrategies, UndecidableInstances #-}\n\n    module Main where\n\n    import Control.Monad.Free\n    import Data.Functor.Adjunction\n\n    data Gree f z where\n      P :: z -> Gree f z\n\nThis file has been truncated. show original\n\nYet another very related variant would be the following pairing:\n\n\n    data Spine f i o where\n      Z :: Spine f x x\n      S :: Spine f i (f o) -> Spine f i o\n\n    data Spree f z where\n      Spree :: Spine f i o -> i -> Spree f o\n\n\nSame but different:\n\n\n    type Compositions :: Nat -> (Type -> Type) -> Type -> Type\n    type family Compositions n f x where\n      Compositions 0 f x = x\n      Compositions n f x = f (Compositions (n - 1) f x)\n\n    data Snee f z where\n      Snee :: SNat n -> Compositions n f x -> Snee f x\n\n\n^ one fun thing about this one is that it’s on display that `join` follows addition of the nat.\n\n…However, all these representations are generally a pain to work with .",
  "title": "Free-like data structure:"
}