2013-07-29 2 views
0

저는 하스켈과 스냅에 상당히 익숙하며 스냅을 사용하는 작은 웹 포럼을위한 프로젝트를 진행하고 있습니다. 내가 겪고있는 문제는 충돌을 이해하고 다음 코드를 해결하는 방법입니다.하스켈 스냅 프레임 워크 - 유형 불일치 ByteString/Maybe ByteString

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

혼란을 정리하기 위해 어떤 조언을 많이 주시면 감사하겠습니다 어떤 방법이 어쩌면 랩을 해제하고 단지를 검색하기 위해, 나는이 검색되었습니다 다음과 같이

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

나에게 형식 불일치 오류를 제공합니다 bytestring하지만 성공하지 못했습니다.

감사합니다.

답변

3

JustMaybe a 유형의 생성자입니다. getParam, 나는 Snap Maybe Bytestring을 반환하므로 bsMaybe Bytestring입니다. Just bs라고 말하면 Maybe (Maybe Bytestring)은 분명히 원하지 않는 것입니다. fromJust :: Maybe a -> a을 찾고 있지만 getParam도 성공했는지 확인하지 않았기 때문에이 이름이 html 페이지에 입력되어 있기 때문에이 기능은 위험합니다.

당신이해야 할 일은 유스 케이스 또는 >>=입니다.

뭔가 편집

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

처럼 당신이 뭘 하려는지 따라 달라집니다. 바인딩은 유용 할 수 있으므로 liftM, lifM2, liftM3

경우에 따라 liftM2를 사용할 수 있습니다. 나는 당신의 타입이 무엇인지 모르지만 나는 아주 간단한 예를 들어 줄 것이다. 당신은 당신이 이것 같이 할 수 있던 2 개의 Bytestrings가 당신을 저장한다.

bs1 <- getParam "one" 
bs2 <- getParam "two" 

case (liftM2 append bs1 bs2) of 
    Nothing -> writeBS "Failed" 
    Just b -> writeBS b 
+0

이 도움이되었습니다. – stickybynature

+0

>>>이 경우에는 >>을 어떻게 사용 하시겠습니까 ?? – stickybynature

1

Maybe a 타입의 값을 추출하는 좋은 방법은 Data.Maybe 모듈에서 fromMaybe 함수를 사용하는 것이다. MaybeNothing 값의 경우 사용할 기본값이 있으면 유용합니다.

데모 코드가 작동하도록 Snap 라이브러리를 가져 오는 것을 피하기 위해 일부 모나드가 아닌 IO 모나드에 예제를 제공 할 예정이지만 동일한 (타입 시그니처 변경 제외) 길이로 작동해야합니다 처리기가 getParam 동작과 같은 모나드에 있으므로 IO (Maybe ByteString)입니다

{-# 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 

getParam1 이후 및 getParam2, 우리는 우리가 내부의 Maybe ByteString 가치를 얻을 수있는 모나드 조치를 사용할 필요가 알고있다.

-- (Type of getParam1 >>= Type of our function to supply) -> Desired type 
IO (Maybe ByteString) -> (Maybe ByteString -> IO ByteString) -> IO ByteString 
: m a -> (a -> m b) -> m b입니다 >>=의 유형 서명,보고

, 우리는 우리가 이러한 특정 유형의 바인딩을 적용 찾고 의미 IO ByteString을 할 Maybe ByteString를 할 유형 a을 설정하고 b를 입력 할 수 있습니다

fromMaybe :: a -> Maybe a -> a 

우리는 부분적으로 fromMaybe을 적용 할 수 염두에두고

, 우리는 fromMaybe의 종류를 볼 수 있습니다 기본 ByteString과 함께 얻을 : 이것은 우리가 getParam1의 결과에 >>=를 사용하는 데 필요한 유형이

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

:

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

이제 우리는 IO에 다시 ByteString을 넣어 return와 해당 기능을 구성 . 우리는 IO 모나드의 do 블록에 있기 때문에, 우리는 <- 바인딩 화살표 구문을 사용하여 더욱 사용하기 위해 ByteString을 추출 할 수 있습니다

:이 시점에서

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

을, 당신은 str1에서 순수한 ByteString해야 do 블록에 맞게 사용하십시오.

이 설명이 도움이 되길 바랍니다.