는 방법이 있을 푸에서 형식 IO 사?
문제
나는 아주 간단한 함수
import qualified Data.ByteString.Lazy as B
getJson :: IO B.ByteString
getJson = B.readFile jsonFile
readJFile :: IO (Maybe Response)
readJFile = parsing >>= (\d ->
case d of
Left err -> return Nothing
Right ps -> return (Just ps))
where parsing = fmap eitherDecode getJson :: IO (Either String Response)
가 jsonFile
은 파일의 경로를물(용서 부족의 표기는,그러나 내가 이것을 더 명확하게 작업)
나의 질문은;는 방법이 있 나를 위해 도랑을 파 IO
부분적으로 일할 수 있도록 가진 파일을까요?
알할 수 있는 패턴 경기에서 특정을 사용해 다음과 같 Either
고 Maybe
자신의 값만을 할 수 있는 이와 유사한 IO
?
또는 목소리가 다르게:이 있습 방법을 만들기 위해 readJFile
return Maybe Response
지 않고 IO?
해결책
내 의견을 확장하려면 다음과 같은 방법이 있습니다.
getJson :: IO B.ByteString
getJson = B.readFile jsonFile -- as before
readJFile :: B.ByteString -> Maybe Response -- look, no IO
readJFile b = case eitherDecode b of
Left err -> Nothing
Right ps -> Just ps
.
결국 하나의 IO 조치의 모든 것을 다시 결합합니다.
getAndProcess :: IO (Maybe Response)
getAndProcess = do
b <- getJson
return (readJFile b)
. 다른 팁
당신이 필요하지 않"끌어다."을 통해 어떤 기능을 하지 않는 한 그들은 모든 필요를 실제로 수행한다.리고 전체 체인으로 설계되었으로 fmap
(나 liftM
/ liftM2
/ ...).
예를 들어,
f1 :: B.ByteString -> K
f2 :: K -> I
f3 :: K -> J
f4 :: I -> J -> M
고의 전체 일정을 다음과 같
m :: M
m = let k = "f1 getJson"
in f4 (f2 k) (f3 k)
은 단순히 할 수 있
m = fmap (\b -> let k = f1 b
in f4 (f2 k) (f3 k) )
getJson
또한,이 보일 수 있습과 멋진 do
표기:
m = do
b <- getJson
return $ let k = f1 b
in f4 (f2 k) (f3 k)
에 관하여 편집하고 질문
이 있습 방법을 만들기 위해
readJFile
returnMaybe Response
이 없IO
?
No, 할 수 있는 가능하게 작업하기 때문에, readJFile
가해야 할 IO.없는 방법에서 탈출 IO
다음 사는 그것의 요점!(물론,거기에 unsafePerformIO
로 리카르도 말하지만 이것은 확실히 유효하지 않은 응용 프로그램를 위한니다.)
의 경우 경고:등급이 부여의 포장을 풀고 Maybe
값 IO
일,그리고 서명으로 괄호에서 그들을 원할 수 있습을 보인 MaybeT
변압기.
readJFile' :: MaybeT IO Response
readJFile' = do
b <- liftIO getJson
case eitherDecode b of
Left err -> mzero
Right ps -> return ps
일반적으로,네,있습니다.반의 많은"이지만"하지만,거기입니다.당신은 무엇이라고 불리는 안전하지 않은 IO 작업: 시스템입니다.IO.안전.그것을 쓰는 데 사용되는 래퍼를 호출할 때는 외부 라이브러리는 일반적으로,그것은 무언가에 리조트에서는 정기는 메인 코드.
기본적으로,당신은 전화 unsafePerformIO :: IO a -> a
는 정확하게 당신이 원하는 것,그것을 밖으로 스트립의 IO
부분과 당신에게 다시 포장 값의 형식 a
.하지만,당신이 문서가 있의 요구 사항을 보장해야 자신 시스템,는 모든 결국에는 동일 아이디어:비록 당신이 수행한 작업을 통해 IO,대답해야의 결과 함수에서 예상대로 다른 어떤켈는 기능이 작동하지 않에 IO
:그것은 항상 동일한 결과를 갖지 않고,부작용 기준으로 입력 값입니다.
여기에서,주어진 코드 이것은 분명히지 않는 경우, 때문에,당신은 파일을 읽.당신은 단지 내에서 작업을 계속 IO 일에,호출하여 귀하의 readJFile
내에서 또 다른 기능으로 결과 유형 IO something
.다음할 수 있 값을 읽어내 IO
래퍼(에 IO
자신),에서 작동한 다음,다시-포장에 결과는 다른 IO
할 때 반환됩니다.
No, there is no safe way to get a value out of the IO monad. Instead you should do the work inside the IO monad by applying functions with fmap or bind (>>=). Also you should use decode instead of eitherDecode when you want your result to be in Maybe.
getJson :: IO B.ByteString
getJson = B.readFile jsonFile
parseResponse :: B.ByteString -> Maybe Response
parseResponse = decode
readJFile :: IO (Maybe Response)
readJFile = fmap parseResponse getJSON
You could also use do notation if that is clearer to you:
readJFile :: IO (Maybe Response)
readJFile = do
bytestring <- getJson
return $ decode bytestring
Note that you dont even need the parseResponse function since readJFile specifies the type.