을 나는 IO 모나드에서 실행되는 기능을 가지고 :컴파일 오류가 복잡한 오류 메시지
withDB :: (forall c. IConnection c => c -> IO b) -> IO b
withDB fn = bracket (connectSqlite3 "int/db.sqlite3") disconnect fn
을 그리고 지금은 일부 MonadIO m
에서 실행을 일반화하기로 결정했다. 나는 방법 다음 그것을했다, 다시 발명으로 bracket
을 내 scope
(당신은 라이브러리의 일부를 알 수 있습니까?) :
Could not deduce (m ~ IO)
from the context (MonadIO m)
bound by the type signature for
withDB :: MonadIO m => (forall c. IConnection c => c -> m b) -> m b
at src\...
'm' is a rigid type variable bound by
the signature for
withDB :: MonadIO m => (forall c. IConnection c => c -> m b) -> m b
Expected type: IO b
Actual type: m b
In the third argument of 'scope' namely 'fn'
In the second argument of '($)', namely
'scope
(liftIO $ connectSqlite3 "int/db.sqlite3")
(\x -> liftIO $ disconnect x)
fn'
그리고 지금 내 질문 :
나는 오류가 발생했습니다scope :: MonadIO m => m a -> (a -> m b) -> (a -> m c) -> m c
scope before after action = do
x <- before
r <- action x
_ <- after x
return r
withDB :: MonadIO m => (forall c. IConnection c => c -> m b) -> m b
withDB fn = liftIO $ scope
(liftIO $ connectSqlite3 "int/db.sqlite3")
(\x -> liftIO $ disconnect x) fn
m ~ IO는 무엇을 의미합니까? 처음 두 줄의 오류는 무엇이라고 말합니까? 또한,이 ~ haskell 코드에서 건설 보았다하지만 그것을 찾을 수 없습니다. 신장? 고정 유형 변수 란 무엇입니까?
오류가 발견되어 해결되었습니다.
scope
전에liftIO $
을 제거하면 충분합니다. 하지만 그냥 재 시도주기였습니다. 이 오류 메시지의에 오류 위치에 대한 정보가 있습니까? 나는 'fn'에 뭔가 잘못된 것을 본다. 좋아, 나는 그것에 대해 조금 생각하고 추측했다 : GHC는 위에서 아래로 타입을 추론한다. 그리고liftIO
은m
이IO
이어야하지만fn
은 일반적인 유형이m
이므로 오류입니다. haskell 컴파일러는 위에서 아래로 유추합니까? 그리고 (더 중요한) GHC가 산출물의 하위 표현에 대해 유추하는 유형을 볼 수 있습니까?
이 긴 질문을 읽어 주셔서 감사합니다.
'scope' 함수는'bracket'과 정확히 똑같지 않습니다. 'bracket '은 계산을 자원 할당/해제의'괄호 '로 래핑 할뿐만 아니라 예외를 처리하여 예외가 발생하더라도 리소스를 해제합니다. 'scope' 함수는 리소스를 해제하지 않고 종료합니다. 어쩌면이 경우에는 중요하지 않지만 여전히 그렇습니다. –
일반 MonadIO가 예외를 처리 할 수 있습니까? – demi
나는 이것을'liftIO'로 관리 할 수 있다고 생각합니다. 결국'IO a -> m a' 타입을 가지며 모든 예외 처리 루틴은'IO' 타입을가집니다.예외 관련 함수는 다음에서 찾을 수 있습니다. http://hackage.haskell.org/packages/archive/base/4.5.0.0/doc/html/Control-Exception.html –