Search code examples
haskellhaskell-snap-framework

Haskell Snap Framework - Type mismatch ByteString / Maybe ByteString


I am fairly new to Haskell and Snap and I am working through my own project for a small web forum using snap. The problem I am having is in understanding the conflict and how to resolve for the following code.

handleCategoryAdd :: H ()
handleCategoryAdd = method POST (withLoggedInUser go)
  where
    go user = do
      bs <- getParam "categoryName"
      cN <- B.unpack $ Just bs
      cD <- getParam "categoryDesc"
      cT <- getCurrentTime
      return (Db.saveCategory (Db.Category 1 cN cT "1" ))
      redirect "/"

Gives me a type mismatch error as follows:

src\Site.hs:118:22:
    Couldn't match expected type `ByteString'
                with actual type `Maybe ByteString'
    In the first argument of `unpack', namely `bs'
    In a stmt of a 'do' block: cN <- unpack bs
    In the expression:
      do { bs <- getParam "categoryName";
           cN <- unpack bs;
           cD <- getParam "categoryDesc";
           cT <- getCurrentTime;
           .... }

Any advice to clear up the confusion would be much appreciated, I have been searching for some way to unwrap the maybe and just retrieve the bytestring but have been unsuccessful.

Many thanks!


Solution

  • Just is a constructer for the type Maybe a. getParam, i'm pretty sure, returns Snap Maybe Bytestring so bs is of type Maybe Bytestring. When you say Just bs you then would have Maybe (Maybe Bytestring) which is clearly what you don't want. You are looking for fromJust :: Maybe a -> a but this function is dangerous because you haven't checked if getParam has even succeeded and there is an input on on the html page with that name.

    What you should do is use cases or >>=.

    Something like

    bs <- getParam "categoryName"
    case bs of
       Nothing -> writeBS "failed"
       Just b  -> do
          let unpacked = B.unpack b
          -- ... Do more stuff
    

    EDIT

    It depends what you are trying to do. Bind can be useful and so can liftM, lifM2, liftM3, etc.

    In your case you may want liftM2. I don't know what your types are but I'll give a very simple example. Save you have have those 2 Bytestrings you could do something like this.

    bs1 <- getParam "one"
    bs2 <- getParam "two"
    
    case (liftM2 append bs1 bs2) of
       Nothing -> writeBS "Failed"
       Just b  -> writeBS b