0

I'm trying to extract a basic post request using code from this question (except that I'm using lbsBackEnd instead of the no-longer-existing lbsSink).

{-# LANGUAGE OverloadedStrings #-}
import Network.Wai.Handler.Warp (run)
import qualified Data.ByteString.Char8 as C
import Network.Wai.Parse (parseRequestBody, lbsBackEnd)
import Network.Wai(Response(..))
import Network.HTTP.Types(status200)
import Blaze.ByteString.Builder

main = run 3000 app

app req = do
  (params, _) <- parseRequestBody lbsBackEnd req
  let r = C.concat $ map (\(x,y) -> C.concat [x,y]) params
  return $ ResponseBuilder 
      status200
      [("Content-Type", "text/plain")]
      $ fromByteString r

Comments in that question suggest that this should work, but I'm getting the type error

Couldn't match expected type `C.ByteString'
            with actual type `bytestring-0.9.2.1:Data.ByteString.Internal.ByteString'
Expected type: [(C.ByteString, C.ByteString)]
  Actual type: [Network.Wai.Parse.Param]
In the second argument of `map', namely `params'
In the second argument of `($)', namely

Which is a bit odd because Network.Wai.Parse docs say that Param is a type synonym for (ByteString, ByteString), so as far as I can tell, this should work.

Any tips on what I'm doing wrong?

Community
  • 1
  • 1
Inaimathi
  • 13,853
  • 9
  • 49
  • 93

1 Answers1

2

Your wai-extra was built using bytestring-0.9.2.1, but you have a newer bytestring package installed. Unless GHC is instructed to use the older version with a -package flag or by hiding the newer, it picks the newest installed version of each package.

The package version is part of the types it defines, so the ByteString of bytestring-0.9.2.1 is not the same type as the ByteString of bytestring-0.10.0.0 (or whatever your newest version is).

You can

  • compile the programme with a -package bytestring-0.9.2.1 flag (but it could be that other used packages are built against a different bytestring version, then that wouldn't work).
  • build the programme as a Cabalized package, then cabal-install would figure out the necessary -package flags and provide them to GHC (if it finds a consistent build plan).
  • rebuild wai-extra (and possibly a lot of other packages) against the newer bytestring version.
  • unregister the newer bytestring version (which might require rebuilding some packages using the old version).
Daniel Fischer
  • 181,706
  • 17
  • 308
  • 431
  • How do I go about "rebuild[ing] `wai-extra` against the newer `bytestring` version"? All the components I'm using were installed via `cabal install` rather than building from source. – Inaimathi Jan 13 '13 at 01:14
  • `cabal-install` builds from source. You can try `cabal install --reinstall wai-extra --dry-run` to check whether it finds a consistent install plan, that probably would work. It might report that that would break some other packages, if these are not too many, add them to the command. If all looks good, remove the `--dry-run` and let it build. You could also first `ghc-pkg unregister` the packages to rebuild. `ghc-pkg` would warn you if that would break installed packages, so you can see whether it's worth the hassle. If it would break too much, `Cabal`izing would be my preferred option. – Daniel Fischer Jan 13 '13 at 01:20
  • I still get the same error after doing `cabal install --reinstall wai-extra`. I've also tried to re-install `bytestring`, `wai` and `warp`; no dice on all of the above. – Inaimathi Jan 13 '13 at 01:34
  • Oh, dang. I forgot that it depends on a ton of other packages that also would have to be rebuilt against the new `bytestring`. So with just `--reinstall`, cabal shied away from reinstalling all those dependencies. Urk. Then you'd have to `unregister` a lot, probably at least half your packages :( It might be easiest to just remove your local package database and after that, `cabal install bytestring` (for the new bytestring version) and `cabal install world` to reinstall everything you had. But do check with `ghc-pkg list` that you really want it (not too many packages) before you do. – Daniel Fischer Jan 13 '13 at 01:44
  • Or just `unregister` the new `bytestring`, that's less work, probably. There should be no huge difference between that and the older version. – Daniel Fischer Jan 13 '13 at 01:46
  • Hm. Well, `ghc-pkg unregister bytestring` did the trick, though I assume this isn't a good general strategy for dependency resolution in Haskell packages. – Inaimathi Jan 13 '13 at 01:53
  • Not really. But when you have multiple versions of a package installed, situations like this can arise. They're bound to arise when it's a package many others depend on, like bytestring. Generally, one shouldn't install other versions of packages that come with GHC (like bytestring, array, containers, directory, ...) unless one knows very well what one is doing. You can install newer versions of those with less danger if you use `cabal-dev`, but then you install a lot of packages multiple times, once per sandbox often. – Daniel Fischer Jan 13 '13 at 01:59