2011-12-19 3 views
1

하스켈과의 자체 학습을 시도하고 있습니다.하스켈 형식 검사

함수 loadData은 파일에서 일부 데이터를 읽고 정수 매개 변수에 따라 일부 처리를 수행하여 맵을 생성합니다. 두 개의 그런지도를 만들고 코사인 유사성 측정 기준을 적용해야합니다. 먼저 두지도의 교차점을 찾으려고합니다. 그러나 형식 오류()가 발생합니다. loadData의 출력을 Map.intersection에 어떻게 공급할 수 있습니까? 기능 어플리케이터 $이 필요합니까? 이 같은

loadData :: Int -> FilePath -> IO (Map.Map [Char] Double) 

Map.intersection :: Ord k => Map.Map k a -> Map.Map k b -> Map.Map k a 
+0

IO 처리 방법을 알고 있습니까? – fuz

+0

'loadData'의 출력을'Map.intersection'에 어떻게 공급하려고합니까? 코드를 보여주세요. – dave4420

+0

방금 ​​Map.intersection을 시도해 보았습니다. <$> (loadData 1 "firstFile") <$> (loadData 1 "secondFile") – atlantis

답변

3

뭔가이의 결과가 IO (Map.Map String Double)을 입력했다고

import Control.Applicative 

Map.intersection <$> loadData param filename1 <*> loadData param filename2 

참고.

+0

IO 기능이 제대로 작동하지 않습니다. 따라서 IOd를 반환하는 loadData에서 readFile을 한 번 수행하면 모나드 컨텍스트에서 영원히 작동해야합니까? 아니면 그냥 '추출'하고 사용하는 방법이 있습니까? – atlantis

+2

값을 '추출'하고 '<$>', '<*>','>> = '등의 함수를 사용하여 값을 사용할 수 있습니다. 그러나 당신은 언제나 '입출력'에서 어떤 것을 끝내게됩니다. –

+4

당신이 모나드 컨텍스트에서 영원히 운영된다고 말하는 것이 더 정확하고, '<$>','<*>'및'>> = '결합자는 단순히 비 -IO 기능을 처리 방법을 알고있는 것으로 변환하는 것입니다 IO 조금. –

4

FUZxxl이 귀하의 질문에 언급 한 바와 같이, 나는 하스켈 I/O를 얼마나 들여다 보는지에 대해 질문합니다. 이것은 언어를 사용하기 위해 극복해야 할 큰 초기 장애물 중 하나이며 더 간단한 작업으로 시작하려는 것 같습니다.

하지만 여전히 귀하의 질문에 더 답하기 위해 두 가지 방법이 있습니다. 첫째, 초등학교 하나, 당신은 다른 사람 전에 먼저 이해하는 데 필요한 하나의 이해 :

processData :: Int -> FilePath -> Int -> FilePath -> IO (Map.Map [Char] Double) 
processData int1 path1 int2 path2 = 
    do map1 <- loadData int1 path1 
     map2 <- loadData int2 path2 
     return (Map.intersection map1 map2) 

함수에 위의 패턴을 추상화 것을 포함 고급 답이 있습니다. 이를 수행하는 더 기본적인 방법은 Control.Monad 모듈의 liftM2 함수를 사용하는 것입니다. 난 그냥이 위의 코드에 관련이 어떻게 분명하게 liftM2의 예 구현을주지 :

processData :: Int -> FilePath -> Int -> FilePath -> IO (Map.Map [Char] Double) 
processData int1 path1 int2 path2 = 
    liftM2 Map.intersection (loadData int1 path1) (loadData int2 path2) 

dave4420의 대답은 다음과 같습니다 liftM2

liftM2 :: Monad m => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r 
liftM2 f mx my = do x <- mx 
        y <- my 
        return (f x y) 

, 우리는 processData이 방법을 다시 작성할 수 있습니다 조금 더 진보 된; 그 이유는 Control.Applicative에 두 개의 연산자 (<$><*>)가 있으며 조합에서는 liftM2과 동일한 작업을 수행 할 수 있지만 liftM2가 첫 번째 인수로 취하는 함수의 임의의 인수 인수에 해당합니다.