akhra

🏴🚩⚧️⚢♾️ΘΔ⚪

  • &🍯she/her 🐲xie/xer 🦡e/em/es

wenchcoat system:
🍯 Akhra (or Melli to disambiguate), ratel.
🐲 Rhiannon, drangolin.
🦡 Lenestre, American badger.

unless tagged or otherwise obvious, assume 🍯🐲🦡 in chorus; even when that's not quite accurate, we will always be in consensus. address collectively as Akhra (she/her), or as wenchcoat (she/her or plural).

💞@atonal440
💕@cattie-grace
❤️‍🔥(not#onhere)
🧇@Reba-Rabbit


Discord (mention cohost, I get spam follows)
@akhra
Discord server ostensibly for the Twitch channel but with Cohost in hospice y'know what let's just link it here
discord.gg/AF57qnub3D

mehbark
@mehbark

idris and lean do this great thing where (a, b, c) is just sugar for (a, (b, c)), and i really wish haskell did this too. there are consequences to not doing it that way (i guess having (,..,) functions is a benefit but that could also be syntax sugar if you really wanted). i'm curious what opinions you have on this extremely important subject and if there's an even better (or worse) way of doing tuples that you've seen


mzero
@mzero

(a, b, c) and (a, (b, c)) aren't isomorphic in Haskell because of laziness.

data Unit = Single

bottom :: a
bottom = error "⊥"

universeTriple :: [(Unit, Unit, Unit)]
universeTriple =
  [ bottom
  , (bottom, bottom, bottom)
  , (bottom, bottom, Single)
  , (bottom, Single, bottom)
  , (bottom, Single, Single)
  , (Single, bottom, bottom)
  , (Single, bottom, Single)
  , (Single, Single, bottom)
  , (Single, Single, Single)
  ]

universePairPair :: [(Unit, (Unit, Unit)]
universePairPair =
  [ bottom
  , (bottom, bottom)
  , (Single, bottom)
  , (bottom, (bottom, bottom))
  , (bottom, (bottom, Single))
  , (bottom, (Single, bottom))
  , (bottom, (Single, Single))
  , (Single, (bottom, bottom))
  , (Single, (bottom, Single))
  , (Single, (Single, bottom))
  , (Single, (Single, Single))
  ]

The values (bottom, bottom) and (Single, bottom) are in (Unit, (Unit, Unit)) but have no equivalents in (Unit, Unit, Unit)

Which isn't too say that having to define instances to arbitrary tuple sizes doesn't suck and cause problems and shouldn't have better language support.


mzero
@mzero

Thinking about this a little more, GHC Haskell allows you to define and unpack strict data fields, so you can define the a pair type with a lazy first element and an unpacked strict second element

data LSPair a b = LSPair a {-# UNPACK #-} !b

and then

type (a, b, c) = LSPair a (LSPair b (LSPair c ()))

akhra
@akhra

Naively, instance Functor ((,) a) is ambiguous with instance Functor ((,,) a b) in this model because you don't know whether the intended payload LSPair c () or LSPair b (LSPair c ()). You'd need to nest fmaps, which IMO kills possibly the only justification for tuples beyond pair in the first place. 😹

But, it's been several years since I've touched Haskell (working on fixing that lol) and there might be a way to resolve this with type families?


akhra
@akhra

lol what if crimes tho

data LSPair a b = LSPair b {-# UNPACK #-} !a

type (a, b) = LSPair b (LSPair a ())
type (a, b, c) = LSPair c (LSPair b (LSPair a ()))

instance Functor (LSPair a)

You must log in to comment.

in reply to @mehbark's post:

in reply to @mzero's post:

in reply to @akhra's post:

...of course the usual advice on working with HLists is also, "don't" 😆

(I did once use something HList-adjacent to do multistage startup without needing intermediate types to pass the partial environment to later stages, just "contains element of type" constraints. Which was all basically to avoid tuples, lol. Actually been thinking about that as a good "get back to Haskell" project tho, I lost access to the module along with my job and it was basically just a couple of type families and some operators, I think under 50 lines, and I had a few ideas for making it less idiosyncratic to the immediate use case that I never had time to explore.)