Looking at that, I guess providing specialized parser combinators directly would be smarter. Have you looked into that?

]]>type FoldJSon r = (HashMap Text r -> r) -> (Vector r -> r) -> (Text -> r) -> (Integer -> r) -> (Double -> r) -> (Bool -> r) -> (() -> r) -> r

(The () parameter to the second-to-last argument is obviously superfluous, I’ve added it to make it clear that this argument is a continuation for the Nil case.)

You could then implement a deserialization API with the following interface:

class FromJSon a where

parseJSon :: FoldJSon (Parser a) -> Parser a

decode :: FromJSon a => ByteString -> Maybe a

in a way exactly analogous to what aeson does, except with some additional inversion of control and no concrete Value type.

I think the name of this game is “refunctionalization”, but I’m not 100% sure.

]]>