{
"$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:"
}