You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
While shift_ is decently expressive, it's ergonomically underpowered right now.
For instance, suppose you want to guard with respect to some property of the stack. With shift you might go
Indexed.do
a <- pop
b <- pop
guard $ p a b
push b
push a
Not ideal but not too bad. At least it's pretty abstract, you don't have to deal with shift all the time. We could implement a peek function too, to improve on this
``haskell
Indexed.do
a <- peek; b <- peek
guard $ p a b
But we can't pop (or peek) with shift_, since the stack may be virtual.
So I end up with functions like this
--| Decimal digit. To manipulate the raw 'Char' instead, use 'digitChar'.digit:: (Cont2.Stackedm, Indexed.Monadm, TokensCharchunkm) =>m (Int->r) rInt
digit =Indexed.do
Cont2.shift_ $\k fl ->Indexed.pure$\i ->if0<= i && i <10then k fl i else fl i -- This is a guardCont2.shift_ $\k fl ->Indexed.pure$\i -> k (\_ -> fl i) (Char.intToDigit i) -- This is a map by the way, so maybe it should be a `stack`
c <- digitChar
Indexed.pure$Char.digitToInt c
where I have to manipulate continuations directly for simple stuff. It's a little too noisy.
I don't really know how to make it possible to abstract this pattern. One way is to define a family of guard functions
guardS0::Stackedm=>Bool->mrr()
guardS0 =Cont2.shift_ $\k fl ->Indexed.pure$if p then k fl else fl
guardS1::Stackedm=> (a->Bool) ->m (a->r) (a->r) ()
guardS1 =Cont2.shift_ $\k fl ->Indexed.pure$\a ->if p a then k fl a else fl a
guardS2::Stackedm=> (a->b->Bool) ->m (a->b->r) (a->b->r) ()
guardS2 =Cont2.shift_ $\k fl ->Indexed.pure$\a b ->if p a b then k fl a b else fl a b
But it feels utterly unsatisfying. There's clearly a pattern here. Can we capture it with a single function? Maybe a type class would do the trick. But doing a type class just for guard feels silly. There's a whole algebra of combinators which can be lifted pointwise to functions, not just if … then … else. This is where I start over-engineering.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
-
While
shift_
is decently expressive, it's ergonomically underpowered right now.For instance, suppose you want to
guard
with respect to some property of the stack. Withshift
you might goNot ideal but not too bad. At least it's pretty abstract, you don't have to deal with shift all the time. We could implement a
peek
function too, to improve on this``haskell
Indexed.do
a <- peek; b <- peek
guard $ p a b
But we can't pop (or peek) with
shift_
, since the stack may be virtual.So I end up with functions like this
where I have to manipulate continuations directly for simple stuff. It's a little too noisy.
I don't really know how to make it possible to abstract this pattern. One way is to define a family of
guard
functionsBut it feels utterly unsatisfying. There's clearly a pattern here. Can we capture it with a single function? Maybe a type class would do the trick. But doing a type class just for
guard
feels silly. There's a whole algebra of combinators which can be lifted pointwise to functions, not justif … then … else
. This is where I start over-engineering.Beta Was this translation helpful? Give feedback.
All reactions