작은 프로젝트를 개발하기 위해 Yesod를 사용하기 시작했습니다. 하스켈을 사용하여 실제 작업을 수행 한 것은 이번이 처음입니다. 등록 양식을 처리 이 코드는 잘 작동 : 하스켈 : non-IO 모나드에서의 예외 처리
postRegisterR :: Handler()
postRegisterR = do email <- runInputPost $ ireq textField "email"
user <- runInputPost $ ireq textField "user"
pwd <- runInputPost $ ireq textField "pwd"
cpwd <- runInputPost $ ireq textField "cpwd"
if pwd == cpwd && isValidEmail email
then do
tryInsert email user pwd
setSession "user" user
redirectUltDest SessionR
else do
redirect HomeR
tryInsert :: Text -> Text -> Text -> Handler()
tryInsert email user pwd = do pwdbs <- liftIO $ hashedPwd pwd
_ <- runDB $ insert $ User email user pwdbs
return()
지금 문제가되고 : 나도 같은 자격 증명을 두 번 로그인하면 내가
InternalServerError
를 얻을. 내 모델 구성에
UniqueUser email username
이 있기 때문에 이것이 옳습니다. 그래서 나는이 오류를 어떻게 든 잡아서 다루기를 원합니다. 외부 라이브러리 나 프레임 워크에 정의 된 non-IO 모나드를 처리 할 때 하스켈에서 예외 처리가 어떻게 작동하는지 일반적으로 어떻게 할 수 있습니까?
추신 : this 튜토리얼을 읽었지만 새 라이브러리를 디자인 할 때 유용합니다. catch 함수를 사용하려고했지만 형식 오류가 많습니다. ScopedTypeVariables
확장
tryInsert :: Text -> Text -> ByteString -> Handler Bool
tryInsert email user pwd = HandlerT (\d -> catch (unHandlerT (runDB $ insert $ User email user pwd) d
>> return True)
(\(e :: SomeException) -> return False))
으로 :
Ambiguous type variable `e0' in the constraint:
(Exception e0) arising from a use of `catch'
Probable fix: add a type signature that fixes these type variable(s)
코드 : 편집
당신에게 Ankur 감사, 당신의 코드는이 오류를 제거하기 위해, 약간의 수정과 협력
편집 2
최종 버전이 bennofs '힌트 후 :
{-# LANGUAGE ScopedTypeVariables #-}
import Control.Exception.Lifted (catch)
import Control.Monad (void)
postRegisterR :: Handler()
postRegisterR = do email <- runInputPost $ ireq textField "email"
user <- runInputPost $ ireq textField "user"
pwd <- runInputPost $ ireq textField "pwd"
cpwd <- runInputPost $ ireq textField "cpwd"
if pwd == cpwd && isValidEmail email
then do
pwdbs <- liftIO $ hashedPwd pwd
success <- tryInsert email user pwdbs
case success of
True -> do setSession "user" user
redirectUltDest SessionR
False -> redirect HomeR
else do
redirect HomeR
tryInsert :: Text -> Text -> ByteString -> Handler Bool
tryInsert email user pwd = do void $ runDB $ insert $ User email user pwd
return True
`catch` (\(e :: SomeException) ->
do return False)
[checkUnique] (http://hackage.haskell.org/packages/archive/persistent/0.3.1.3/doc/html/Database-Persist.html#v:checkUnique)를 사용하여 키가 맞는지 테스트 할 수 있습니다. 삽입하기 전에 고유해야하며 해당 케이스를 다르게 처리하여 예외를 피하십시오. – bennofs
음 ... Yesod의 최신 버전에는 checkUnique가 없습니다. 그러나 [insertUnique] (http://hackage.haskell.org/packages/archive/persistent/latest/doc/html/Database-Persist-Class)를 발견했습니다. .html # v : insertUnique), 감사합니다. 어쨌든 나는 아직도 예외 처리에 관심이있다. – andrebask
'ScopedTypeVariables' 언어 확장을 사용하고'(\ (e :: SomeException) -> return False)' – Ankur