1. 2

      I’ve updated the benchmarks to include “buffer-builder”. It’s not very different from “aeson”.

      jsonifier/1kB          mean 2.087 μs  ( +- 260.0 ns  )
      jsonifier/6kB          mean 12.33 μs  ( +- 222.2 ns  )
      jsonifier/60kB         mean 118.3 μs  ( +- 1.991 μs  )
      jsonifier/600kB        mean 1.270 ms  ( +- 38.92 μs  )
      jsonifier/6MB          mean 20.53 ms  ( +- 1.042 ms  )
      jsonifier/60MB         mean 194.9 ms  ( +- 15.04 ms  )
      aeson/1kB              mean 6.542 μs  ( +- 199.2 ns  )
      aeson/6kB              mean 31.25 μs  ( +- 494.5 ns  )
      aeson/60kB             mean 261.7 μs  ( +- 8.044 μs  )
      aeson/600kB            mean 3.395 ms  ( +- 114.6 μs  )
      aeson/6MB              mean 30.71 ms  ( +- 701.0 μs  )
      aeson/60MB             mean 277.1 ms  ( +- 4.776 ms  )
      lazy-aeson/1kB         mean 6.423 μs  ( +- 83.69 ns  )
      lazy-aeson/6kB         mean 30.74 μs  ( +- 607.0 ns  )
      lazy-aeson/60kB        mean 259.1 μs  ( +- 4.890 μs  )
      lazy-aeson/600kB       mean 2.511 ms  ( +- 18.71 μs  )
      lazy-aeson/6MB         mean 24.92 ms  ( +- 95.36 μs  )
      lazy-aeson/60MB        mean 248.6 ms  ( +- 736.6 μs  )
      buffer-builder/1kB     mean 5.512 μs  ( +- 77.39 ns  )
      buffer-builder/6kB     mean 30.29 μs  ( +- 459.9 ns  )
      buffer-builder/60kB    mean 307.0 μs  ( +- 3.640 μs  )
      buffer-builder/600kB   mean 3.001 ms  ( +- 75.72 μs  )
      buffer-builder/6MB     mean 33.05 ms  ( +- 336.3 μs  )
      buffer-builder/60MB    mean 308.5 ms  ( +- 3.489 ms  )
      
    1. 3

      Looks pretty neat! Though I do wonder whether creating two new entirely separate libraries ptr-poker and jsonifier is really necessary. There already is the store-core package which seems to do about the same as ptr-poker, and it might be possible to optimize aeson using jsonifier’s approach.

      1. 1

        I don’t see anything bad in having more packages. It lets the authors of different solutions continue research in different directions. It drives competition raising the overall quality of the ecosystem. It provides separation of concerns, better focus on the problem and provides more space for the author to experiment without having to approve any decision. It makes the author responsible for maintenance of his code, instead of maintainers of the package which he would have PR’ed to. Finally it lets the author collect the reputational benefits in the community for his work.

        Concerning “store-core”, as you may notice in the type definitions, the abstractions are not the same and they don’t exactly fit the requirements of the presented approach.

        Concerning “aeson”. It can be updated to utilise the benefits of “jsonifier” by depending on it and replacing its Encoding abstraction with it. No need to bundle “jsonifier” as part of “aeson” for that. Also not everyone agrees with the design of “aeson” with its typeclass centrism, myself including. I believe that “aeson” lacks in flexibility and its typeclass layer introduces a redundant complication to the otherwise straightforward problem of composing with functions. E.g., here’s a take on that problem from the author of the Elm language. So “jsonifier” approaches that problem as well, serving the needs of people sharing that vision. In fact, the design of “jsonifier” is quite similar to that of Elm’s JSON encoding lib.

      1. 2

        I’m wondering what this has that http://hackage.haskell.org/package/fn doesn’t (disclosure, I’m one of the primary authors).

        [edit] 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…

        1. 2

          Compared to Fn,

          • Strelka provides higher-level abstractions with simpler signatures, e.g.:

              -- Fn
              method :: StdMethod -> Req -> IO (Maybe (Req, a -> a))
            
              -- Strelka
              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

          • Server-agnostic

          • 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.