I appreciate the idea, and also find some other libraries excessively abstract (e.g. servant), but the API for this library feels really bad. consumeSegmentIfIs, ensureThatAcceptsHTML, ensureThatMethodIsGet – those are very verbose. Haskell already has parser combinators in base, namely ReadP, so why not use some of the API conventions shared by that module and other parsers?
I agree. In the example I had a hard time determining what URLs it actually responded to.
I’m wondering what this has that http://hackage.haskell.org/package/fn doesn’t (disclosure, I’m one of the primary authors).
 Actually, looks like strelka might actually be doing less, as you aren’t able to write handlers that take typed arguments, as far as I can tell. So this really just looks like the type of routing that Snap and Happstack have had for years and years…
Compared to Fn,
Strelka provides higher-level abstractions with simpler signatures, e.g.:
method :: StdMethod -> Req -> IO (Maybe (Req, a -> a))
getMethod :: Monad m => RequestParser m ByteString
No custom type-classes or operators. Instead the standard interfaces like Alternative and Monad are used
Streaming of both the request and the response bodies, instead of aggregating them in memory
API is isolated, providing for clarity and nudging the users towards separation of concerns
API is also isolated on the package-level, having all the features that the end-user won’t need located in a separate package (“strelka-core”).
Since it’s only the first official release, some features are yet to be implemented. E.g., the parameters' and URL-encoded body parsers are already slated. But overall, since you’re asking, IMO, Strelka is much simpler and more intuitive than any of the mentioned libraries, yet it aims to let the user solve the tasks of any complexity.
For those wondering, “strelka”, or rather “стрелка”, means arrow in Russian.
Even more relevant: Railroad switches do a form of routing, too.
seems like a less useful version of servant. “Not using type machinery” isn’t an automatic plus.
I have never had to spend more than two minutes debugging router issues in any other language/framework I’ve used (Elixir/Phoenix, Ruby/Rails, Scala/Play, JS/Express, Perl/Catalyst, a few more). Might be two minutes total.
Looking at so many Haskell libraries like this, where a totally normal and basically solved problem is made immensely more complex than it needs to be, really turns me off. Developer hostility with no clear payoff. I get that complex problems can be solved elegantly in Haskell, but wow, simple problems look like they cause an outsized amount of suffering.
I’m not too convinced by this solution, but basic routing as seen in most languages and frameworks is pretty much a solved problem in haskell. But the reason there are so many is that some people are not satisfied by the way it’s done in other languages and prefer to use haskells strong points to get a few more static safeguards.
Yesod does it acceptably with template haskell, allowing us to have statically checked links inside the application, but the Servant framework really is the best in my opinion, as while the actual library is based on some pretty advanced type theory, it’s really simple to define a route and implement it, and all it’s “type machinery” really does is allow you to define every single element of the route, such as query params, authorization… in a easy to use, composable manner.
Although a Haskell enthusiast, I agree totally with this! I think that Haskell needs to have a nicer “core language” story, where you’re calling into Haskell from an impure shell of Python (or what have you) and allowing the pure portions to do their thing without polluting them with the complexities necessary to treat impure actions as pure.
The worst thing is that some of the contortions necessary to wrap your head around IO and impurity make some of the other abstractions seem worse or more intimidating than they are, leading to derision of people who say “no, really, monads are very useful!”