2010-07-10 11 views
1

나는 블로그 중 하나에서 일부 코드 세그먼트를 시도하고 있었고, 난 내가 [7,12,11,20] 얻고 실행하는 동안 다음과 같은 코드를왜이 유형 오류가 발생하지 않습니까?

f :: Int -> [Int] 
f x = [1+x,2*x] 

test :: IO() 
test = putStrLn . show $ return 5 >>= f >>= f 

을 통지했다. 왜 두 번째 'f'함수 호출이 타입 에러를 던지지 않는가? 그것은 List Monad와 관련이 있습니까?

답변

4

일부 하위 식에 대해 유형이 무엇인지 GHC에 문의하겠습니다.

> :t putStrLn . show 
putStrLn . show :: (Show a) => a -> IO() 

확실히 예상대로입니다.

> :t return 5 >>= f >>= f 
return 5 >>= f >>= f :: [Int] 

우리가 예상 했겠지만 귀하의 질문에 대답하지 않습니다. 다음으로, 그 표현이 구문 분석 방법에 대한 빠른 알림 :

> :i (>>=) 
class Monad m where 
    (>>=) :: m a -> (a -> m b) -> m b 
    ... 
infixl 1 >>= 

좋아, 그것은 연관을 왼쪽, 그래서 표현은 (return 5 >>= f) >>= f입니다.

> :t return 5 >>= f 
return 5 >>= f :: [Int] 

(>>=)에 대해 위의 유형 서명이 비교, 우리는 두 가지를 관찰 할 수있다 :

  • (>>=)의 첫 번째 인수해야

    • (>>=)의 두 번째 인수는 모나드의 일종을 반환해야 동일한 모나드의 값

    따라서 f은 e (a -> m b) 여기에 f에 대한 실제 유형 서명은 Int -> [Int]입니다.그래서 우리는 수동으로 유형을 결합 할 수 있습니다 : ([] a)[a]과 같은 일을 의미

    • a = Int
    • b = Int
    • m = []

    하는 것으로.

    그래서 모나드는 실제로 모나드입니다. 무슨 일 이니?

    > return 5 :: ([] Int) 
    [5] 
    > [5] >>= f 
    [6, 10] 
    > ([5] >>= f) >>= f 
    [7, 12, 11, 20] 
    
  • +0

    답을 고맙습니다. 이제 어떻게 작동하는지 이해했습니다. 모나드에 대해 배울 점이 많은 것처럼 보입니다. – jijesh

    6

    목록이 모나드이기 때문에 정확하게 나타납니다. 우리는이 같은 또한 목록 모나드, return x = [x]에서

    concatMap f $ concatMap f $ return 5 
    

    로, 그래서, 그래서 당신은,리스트 모나드, (>>=) = flip concatMap에서

    return 5 >>= f >>= f 
    

    concatMap f $ concatMap f [5] 
    

    이제 concatMap g x = concat (map g x), 그래서 우리는 그것을 확장 할 수 있습니다.

    과 이해가 그것을

    concat $ map f $ concat $ [[6, 10]] 
    concat $ map f $ [6, 10] 
    concat $ [[7, 12], [11, 20]] 
    [7, 12, 11, 20] 
    

    합니까 평가?

    +0

    감사합니다. 나는 <- 리턴 5와 혼동하여 a = 5라고합시다. – jijesh

    관련 문제