I don't understand why Zig's `Io` is a "monad". In fact I discussed that with the author of this article and the author of Zig here, but no conclusion was reached (https://news.ycombinator.com/item?id=46129568).
But, flipping the script, if you want to see something like Zig's `Io` interface in Haskell then have a look at my capability system Bluefin, particularly Bluefin.IO. The equivalent of Zig's `Io` is called `IOE` and you can't do IO without it!
Regarding custom allocators and such, well, that could fit into the same pattern, in principle, since capabilities/regions/lifetimes are pretty much the same pattern. I don't know how one would plug that into Haskell's RTS.
Agreed, Zig's IO is closer to the effect handler / capability passing model. And by closer, I mean exactly the same [1]. However, it's related to monads by duality. A comonadic program is a program that depends on context, which captures the notion of passing capabilities around.
[1] Languages designed around capability passing often have other features, like capture checking to ensure capabilities aren't used outside the scope where they are active. There are only two such languages I know of. Effekt (see https://effekt-lang.org/tour/captures) and Scala 3 (see https://docs.scala-lang.org/scala3/reference/experimental/cc...) However, this is not core to the idea of capability passing.
> the programmer can't tell if the program is actually
What do you mean, "can't tell"? If I see this in Python
(A)(B)(C)
how do I know which of your 9 it means? Well, I'm a Python programmer so I know that it means
A(B)(C)
which is the function A applied to B, which returns a function that gets applied to C. If you're a Haskell programmer you know that it means the same thing.
I grant you that it is odd to those who are unfamiliar and it took me quite a while to get used to it, but it's much better to write that way in Haskell when writing programs that use higher-order functions.
There are a few different ways to cook this up. Here's one:
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens
data Cat = Cat { _age :: Int }
deriving Show
makeLenses ''Cat
data Item
= I Int
| L [Item]
| C Cat
deriving Show
makePrisms ''Item
cat :: Cat
cat = Cat 3
l :: [Item]
l = [I 1, L [I 2, C cat], I 4]
l' :: [Item]
l' = set (ix 1 . _L . ix 1 . _C . age) 9 l
ghci> l'
[I 1,L [I 2,C (Cat {_age = 9})],I 4]
I'm curious whether it's the author's contention that the signatories of the Agile Manifesto thought that the ideas they were championing went back only a few years, and they had no idea they went back at least 30. In particular
> All of these things were later claimed as Agile innovations
Are there some references that demonstrate that? [EDIT: that the signatories thought they were their own innovations]
And if so, is that a bad thing? Ideas are repeatedly rediscovered. This article isn't called "Saying goodbye to Royce, Bell and Thayer", and I'm wondering why not.
It's as if people believed that all the microcomputing software of the 1970s and 1980s, from VisiCalc to Zork to the Macintosh, was done by waterfall design.
> Agile doesn't have that, there is no functional equivelant of "the cake should be moist and rise evenly".
That's not true for the way I understand agile. The way I understand it, the testable outcome is whether the principles of the agile manifesto are satisfied
For example, is your highest priority to satisfy the customer through early and continuous delivery of valuable software? If not then you're not agile.
newtype FlippedIO a = MkFlippedIO { runFlippedIO :: IO a }
deriving Functor
instance Applicative FlippedIO where
pure = MkFlippedIO . pure
liftA2 f (MkFlippedIO x) (MkFlippedIO y) =
MkFlippedIO ((flip . liftA2 . flip) f x y)
data Person = Person String String
deriving Show
putStrLnFlipped = MkFlippedIO . putStrLn
getLineFlipped = MkFlippedIO getLine
getPerson :: IO Person
getPerson = runFlippedIO $
Person
<$> (putStrLnFlipped "Enter your first name:" *> getLineFlipped)
<*> (putStrLnFlipped "Enter your last name:" *> getLineFlipped)
It runs things "backwards":
ghci> getPerson
One
Enter your last name:
Two
Enter your first name:
Person "Two" "One"
In any case, anywhere they’re doing HTTP calls they are already threading IO, so they don’t have to pay an additional cost.
reply