4

형식이없는 언어에서도 가능하지만 반복 증분으로 추가를 정의하는 방법을 찾을 수 없습니다. 여기 내 코드입니다 : 내가 add2 얻을반복되는 증분을 사용하여 유형화 된 교회 숫자에 더하기를 구현할 수 있습니까?

{-# LANGUAGE RankNTypes #-} 
type Church = forall a . (a -> a) -> (a -> a) 

zero :: Church 
zero = \f -> id 

inc :: Church -> Church 
inc n = \f -> f . n f 

-- This version of addition works 
add1 :: Church -> Church -> Church 
add1 n m = \f -> n f . m f 

-- This version gives me a compilation error 
add2 :: Church -> Church -> Church 
add2 n m = n inc m 

컴파일 오류가

Couldn't match type `forall a1. (a1 -> a1) -> a1 -> a1' 
        with `(a -> a) -> a -> a' 
    Expected type: ((a -> a) -> a -> a) -> (a -> a) -> a -> a 
     Actual type: Church -> (a -> a) -> a -> a 
    In the first argument of `n', namely `inc' 
    In the expression: n inc m 
    In an equation for `add2': add2 n m = n inc m 

입니다 왜이 오류가? 은 그 ((a->a) -> a -> a)의 동의어가 아닙니까?

+1

[이 최근 질문] (http://stackoverflow.com/q/23532659/791604)을 원할 수도 있습니다. –

+0

실제로 사용하려면, 동의어를 입력하는 대신 newtype을 사용하는 것이 좋습니다. – PyRulez

답변

5

추가 유형의 특수 효과가 추가 되더라도 코드를 입력 할 수 없지만 충분히 영리하지 못했습니다. (I도. ImpredicativeTypes을 추가하는 시도) 여기 문제가 정의에

type Church = forall a. (a -> a) -> (a -> a) 

a 만 (즉, 내부 foralls없이) 순위 - 0 유형으로 인스턴스화 할 수 자체가하지 않은 Church 것을 생각 . 따라서이 방법으로 정의 된 교회 번호를 inc에 적용 할 수 없습니다.

그러나 다소 장황한 해결 방법이 있지만 다르게 작동하게 만들 수 있습니다. Church을 형식이 아닌 newtype으로 만들어 외부에서 단일 형태로 처리 할 수 ​​있도록합니다. 다음은 모두 작동합니다 :

{-# LANGUAGE RankNTypes #-} 
newtype Church = Church { runChurch :: forall a . (a -> a) -> (a -> a) } 

zero :: Church 
zero = Church (\f -> id) 

inc :: Church -> Church 
inc n = Church (\f -> f . runChurch n f) 

add2 :: Church -> Church -> Church 
add2 n = runChurch n inc 
+2

나는 monomorphic이 올바른 단어가 아니라고 생각한다; 'a'는 _rank-0_ 유형으로 만 인스턴스화 될 수 있습니다. – leftaroundabout

+0

@leftaround 정보가 없습니다. 비록 그것이 여전히 유형 변수를 포함하고 있다면 그것이 진정으로 monomorphic 아니지만 나는 거의 동의어로 용어를 생각 해왔다. –