문제

나는 아주 간단한 함수

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 부분적으로 일할 수 있도록 가진 파일을까요?

알할 수 있는 패턴 경기에서 특정을 사용해 다음과 같 EitherMaybe 자신의 값만을 할 수 있는 이와 유사한 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 return Maybe Response 이 없 IO?

No, 할 수 있는 가능하게 작업하기 때문에, readJFile 가해야 할 IO.없는 방법에서 탈출 IO 다음 사는 그것의 요점!(물론,거기에 unsafePerformIO 로 리카르도 말하지만 이것은 확실히 유효하지 않은 응용 프로그램를 위한니다.)

의 경우 경고:등급이 부여의 포장을 풀고 MaybeIO 일,그리고 서명으로 괄호에서 그들을 원할 수 있습을 보인 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.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top