2016-08-18 14 views
4

나는 같은 IO의 맥락에서 몇 가지 데이터 유형이 : 나는 하나의 데이터 객체처럼 함께 그들 모두를 데려 가고 싶다는변환 - IO에 (A> IO 나) (A -> B)

a :: IO String 
b :: IO FilePath 
c :: String -> IO String 

을 :

data Configdata = Configdata String FilePath (String -> String) 

은 그래서 IO의 문맥 자체에 대한 각 값을 얻을 필요는 없지만, 단지 IO Configdata 중.

해결 방법이없는 중요한 점은 String -> IO StringIO (String -> String)으로 변환 할 수 있다는 것입니다. Hoogle은이 작업을 수행 할 수있는 기능을 제공하지 않습니다.

함수의 입력이 무한하기 때문에 어쩌면 불가능할지 모르겠습니다.

해결책이나 설명이있는 사람이 있습니까? 함수 대신 목록을 사용하는 것은 옵션이지만 가능한 경우 함수를 사용하는 것이 좋습니다.

+14

정말 호환되지 않습니다. 'String -> IO String'에서 IO 계산은 인수에 의존 할 수 있습니다. 'IO (String -> String)'에 의존 할 수 없습니다. – Bergi

+1

@Bergi가 완벽하게 말했습니다. 이것은 Applicative와 Monad의 주요 차이점입니다. – user2297560

답변

10

실제로 이것은 불가능합니다. 기능을 고려 : 그것은 IO (String -> String)이를 변화시킬 수 있다면

이제
import Acme.Missiles 

boo :: String -> IO String 
boo "cute" = return "Who's a nice kitty?" 
boo "evil" = launchMissiles >> return "HTML tags lea͠ki̧n͘g fr̶ǫm ̡yo​͟ur eye͢s̸ ̛l̕ik͏e liq​uid pain" 

, 그것은 순수한 String -> String 기능을 반환하기 전에 all possible IO actions for any input을 실행해야합니다. 비록 당신이 새끼 고양이 관찰 목적으로 만 기능을 사용할 계획이라 할지라도, 그것은 핵 전파를 수반 할 것입니다.

그럼에도 불구하고 특정 응용 프로그램에 대해 을 수행 할 수 있습니다. 특히 함수가 미리 결정된 문자열 집합에 대해서만 호출 될 것이라는 것을 알고 있다면 IO에서 미리 쿼리하고 결과를지도에 저장 한 다음 순전히 색인을 생성 할 수 있습니다.

import qualified Data.Map as Map 

puh :: IO (String -> String) 
puh = fmap ((Map.!) . Map.fromList) . forM ["cute"] $ \q -> do 
     res <- boo q 
     return (q, res) 

물론 이것은 성능 측면에서 실현 가능하지 않을 수 있습니다.

+2

미리 결정된 문자열 집합이있는 경우 집합의 문자열 당 하나의 값으로 작은 사용자 정의 형식을 만드는 것이 좋습니다. 그런 다음 우주 패키지는 당신에게''sequenceA :: (Foo -> IO String) -> IO (Foo -> String)'] (http://hackage.haskell.org/package/universe-1.0/docs/Data)를 줄 수 있습니다. -Universe-Instances-Reverse.html # t : Traversable), 당신이'Map'을 만들고 그것에 색인을 붙이는 행위를 묘사합니다. –