KDL is a nifty configuration language I recently found, and I think it’d be cool to start seeing more uses of it. There was a Haskell library to parse it, but that library didn’t have an easy API to decode the AST into a custom type. So I vendored that library and exposed a decoding API, with plans to rewrite the parser eventually to make it v2-compliant + preserve formatting information.
The thing I’m most excited about with kdl-hs is that it enables decoding with both Arrows notation and Monad do-notation. If you use Arrows notation, you can statically get the full schema of the Decoder without running anything. You get this feature with ApplicativeDo as well, but with Arrows, you can decode values based on previously decoded values, which you can’t do with Applicative alone.
While I think it’d be cool, I personally would rather see TOML. With Rust and Python using TOML, I see TOML as being an easy way to signal to people outside the Haskell world that Haskell is/could be a mainstream language. KDL would still be better than the Haskell-specific Cabal format though.
I doubt that the self-inflicted pain of TOML would buy us that much signalling to get Haskell into the “mainstream” league. I’d rather have something expressive, clean (like KDL!), and shared with the others (thus having editor support etc.)
Sorry for the ranting, I just want to see nice language proliferating and unergonomic parser-pleasers to go dodo.
The main complain about Cabal’s syntax stems from the fact that you have to spend more time editing it than with other software project systems.
If kdl-hs had a comment-preserving parser that would be a point in its favour, otherwise we’re back to step one with a syntax that is not even 10 years old and for which there is very little knowledge in our community.
AST appears to carry the comments and should be formattable
If that’s indeed the case, kudos to @brandonchinn178 for the forethought!
Otherwise, that’s a valid and important feature request.
Yes, the AST is future-facing, which I adapted from kdl-rs. But the parser doesn’t actually populate these correctly right now (I wanted to get a MVP out the door first). It seems like there’s excitement here, though, so maybe I’ll take a stab at it!
I realise I’m kind of moving the goalposts, but you can do this if you add custom functions, like this:
KDL.dashNodesWith "rules" $
switch KDL.arg $ do
case "a" $ pure RuleA
case "b" $ RuleB <$> KDL.children (KDL.argAt "foo")
casefail ("Invalid rule: " <>)
In fact, I think you could implement this using selective functors (maybe something like this already exists?)
Yeah, could probably make that particular pattern work. But still wouldnt have the full power of pattern matching, or pattern match on two KDL.args at the same time (case (arg1, arg2) of ...).
But you could use the Arrow combinators explicitly, it would just be tedious without the desugaring:
KDL.dashNodesWith "rules" $
(toEither <$> KDL.arg) >>> fromEither
where
toEither = \case
"a" -> Left ()
"b" -> Right $ Left $ ()
name -> Right $ Right $ "Invalid rule: " <> name
fromEither =
-- "a"
pure RuleA |||
-- "b"
(RuleB <$> KDL.children (KDL.argAt "foo")) |||
-- else
KDL.Arrow.fail
EDIT: Released kdl-hs-0.2.1, which adds KDL.Applicative and documents this