mono-traversable의 "concatMap"은 어떻게 일반적인 논증을 "풀 아웃"할 수 있습니까?


9

나는 Haskell을 배우고 있으며 이해하기 어려운이 동작을 우연히 발견했을 때 Yesod에 대한 간단한 DB 시드 프로그램을 수행하고있었습니다.

testFn :: Int -> Bool -> [Int]
testFn a b = if b then replicate 10 a else []

Yesod GHCI 세션 :

$ :t concatMap testFn [3]
concatMap testFn [3] :: Bool -> [Int]
$ (concatMap testFn [1,2,3]) True
[1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3]

어떻게 든 각 매핑에서 두 번째 "Bool"을 단일 커리 인수로 "풀"할 수있었습니다.

표준 기본 Prelude GHCI 세션은이 표현식을 컴파일하지도 않습니다.

$ :t concatMap testFn [3]
error:
     Couldn't match type 'Bool -> [Int]' with '[b]'
      Expected type: Int -> [b]
        Actual type: Int -> Bool -> [Int]
     Probable cause: 'testFn' is applied to too few arguments
      In the first argument of 'concatMap', namely 'testFn'
      In the expression: concatMap testFn [3]

Yesod 사용하는 끈다는 모노 -에 이동 그것의 자신의 라이브러리를 concatMap:

$ :t concatMap
concatMap
  :: (MonoFoldable mono, Monoid m) =>
     (Element mono -> m) -> mono -> m

현재의 Haskell 이해 수준에서 여기에 유형이 어떻게 분포되어 있는지 알 수 없었습니다. 누군가이 트릭이 어떻게 수행되는지 나에게 (가능한 한 초보자 지향) 설명 할 수 있습니까? testFn위의 어느 부분이 Element mono유형을 준수 합니까?

답변:


6

우리가 아는 몇 가지 유형을 나열하는 것으로 시작합니다. (우리는 숫자가 Int단순함을 가장합니다 . 이것은 실제로 관련이 없습니다.)

testFn :: Int -> Bool -> [Int]
[1,2,3] :: [Int]
True :: Bool

(concatMap testFn [1,2,3]) True와 동일 concatMap testFn [1,2,3] True하므로 concatMap모든 인수와 일치하는 유형 이 있어야합니다.

concatMap :: (Int -> Bool -> [Int]) -> [Int] -> Bool -> ???

???결과 유형은 어디에 있습니까 ? 연관성 규칙 ->으로 인해 오른쪽에 연결되므로 위의 입력은 다음과 같습니다.

concatMap :: (Int -> (Bool -> [Int])) -> [Int] -> (Bool -> ???)

그 위에 일반 유형을 작성합시다. 유사성을 표시하기 위해 몇 개의 공백을 추가하고 있습니다.

concatMap :: (MonoFoldable mono, Monoid m) =>
             (Element mono -> m              ) -> mono  -> m
concatMap :: (Int          -> (Bool -> [Int])) -> [Int] -> (Bool -> ???)

아하! 우리가 선택하면 우리는 경기가 m같은 Bool -> [Int], 그리고 mono으로 [Int]. 그렇게하면 제약 조건을 충족시키고 MonoFoldable mono, Monoid m(아래 참조) Element mono ~ Int모든 유형 검사를 수행합니다.

우리 ???[Int]의 정의에서 나온 것으로 추론한다 m.

제약 조건에 대해 :에 대해서는 MonoFoldable [Int]말할 것이 거의 없습니다. [Int]목록-같은과 유형 분명히 Int요소 유형은, 그는로를 만들기 위해 충분 MonaFoldable와 함께 Int그 같은 Element.

의 경우 Monoid (Bool -> [Int])조금 더 복잡합니다. 우리는 모든 함수 유형 A -> B이 monoid라면 Bmonoid입니다. 이 작업은 포인트 방식으로 수행됩니다. 우리의 특정한 경우에, 우리는에 의존 [Int]모노 이드 인 우리가 얻을 :

mempty :: Bool -> [Int]
mempty = \_ -> []

(<>) :: (Bool -> [Int]) -> (Bool -> [Int]) -> (Bool -> [Int])
f <> g = \b -> f b ++ g b

1
좋은 설명! 타입을 설명하고 정렬 한 방식은 내가보고 싶은 것입니다. 감사합니다!
dimsuz
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.