0

私は Haskell と Snap を初めて使用し、snap を使用して小さな Web フォーラムで自分のプロジェクトに取り組んでいます。私が抱えている問題は、次のコードの競合と解決方法を理解することです。

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 "/"

次のようなタイプの不一致エラーが表示されます。

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;
           .... }

混乱を解消するためのアドバイスをいただければ幸いです。多分をアンラップしてバイト文字列を取得する方法を探していましたが、うまくいきませんでした。

どうもありがとう!

4

2 に答える 2

1

型から値を抽出する良い方法は、モジュールから関数Maybe aを使用することです。の値の場合に使用するデフォルト値がある場合に便利です。fromMaybeData.MaybeNothingMaybe

デモ コードが動作するために Snap ライブラリをプルすることを避けるために、一部の Snap モナドではなく IO モナドで例を示しますが、ハンドラーが動作する限り、(型シグネチャの変更を除いて) 同じように動作するはずです。getParamアクションと同じモナドで。

{-# LANGUAGE OverloadedStrings #-}
import           Data.Maybe
import           Data.ByteString.Char8 (ByteString)
import qualified Data.ByteString.Char8 as B

getParam1, getParam2 :: IO (Maybe ByteString)
getParam1 = return $ Just "Hello"
getParam2 = return $ Nothing

main :: IO ()
main = do
   str1 <- getParam1 >>= return . fromMaybe "No value"
   str2 <- getParam2 >>= return . fromMaybe "No value"

   B.putStrLn str1
   B.putStrLn str2

getParam1getParam2はであるため、内部IO (Maybe ByteString)の値を取得するにはモナド アクションを使用する必要があることがわかります。Maybe ByteString

の型シグネチャ ( >>=is ) を見ると、 type を be に、 typeを beにm a -> (a -> m b) -> m b設定できます。つまり、これらの特定の型にバインドを適用しようとしています。aMaybe ByteStringbIO ByteString

-- (Type of getParam1 >>= Type of our function to supply)    -> Desired type 
IO (Maybe ByteString) -> (Maybe ByteString -> IO ByteString) -> IO ByteString

それを念頭に置いて、次のタイプを見ることができますfromMaybe

fromMaybe :: a -> Maybe a -> a

デフォルトの ByteString を使用して fromMaybe を部分的に適用し、次を取得できます。

fromMaybe "No value" :: Maybe ByteString -> ByteString

次に、その関数を構成してreturnByteStringback inを配置しIOます。

return . fromMaybe "No value" :: Maybe ByteString -> IO ByteString

これは、>>=の結果で使用する必要がある型ですgetParam1

モナドのdoブロックにいるので、バインド矢印構文を使用して、さらに使用するために を抽出できます。IOByteString<-

str1 <- getParam1 >>= return . fromMaybe "No value"

この時点で、ブロックに適合するように使用する純粋なByteStringインがあります。str1do

この説明がお役に立てば幸いです。

于 2013-08-12T18:55:45.910 に答える