2014-11-16 3 views
0

유형 정보/다운 캐스트를 다형 값으로 지우는 방법은 haskell에 있습니까?RankN 유형 및 패턴 일치

이 예제에서는 Int 또는 Char 중 하나를 포함 할 수있는 박스형 T가 있습니다. 그리고 어떤 형식인지 모른 채이 값을 추출하는 함수를 작성하고 싶습니다.

{#- LANGUAGE RankNTypes -#} 

data T = I Int | C Char 

-- This is not working because GHC cannot bind "a" 
-- with specific type Int and Char at the same time. 
-- I just want a polymorphic value back ;(
getValue :: T -> (forall a. a) 
getValue (I val) = val 
getValue (C val) = val 

-- This on the other hand works, because the function 
-- is local to the pattern matching expression 
onValue :: T -> (forall a. a -> a) -> T 
onValue (I val) f = I $ f val 
onValue (C val) f = C $ f val 

마지막에 유형을 입력하지 않고이 값을 추출 할 수있는 함수를 작성하는 방법이 있습니까?

첫 번째 것과 같은 getValue 함수?

충분히 명확하지 않은 경우 알려주십시오.

답변 그래서 질문 AndrewC으로 바보 (주석에서)와 YellPika는 지적했다. 무한 유형은 의미가 없습니다.

J. Abrahamson은 내가 찾고있는 것에 대한 설명을 제공하므로 해결책으로 해결책을 제시합니다.

P .: 나는 매번 새로운 유형을 원하지 않으므로 GADT를 사용하고 싶지 않습니다.

+2

'getValue'는 * any * a를 제공 할 수 없습니다. 단지'Char' 또는'Int' –

+0

그래, 나도 알아,하지만이 정보를 잃고 싶다. 그냥 값으로 사용하십시오. –

+1

컴파일러가 유형을 추론 할 수없는 값으로 무엇을 하시겠습니까? 진실로 데이터가 어떤 타입인지 신경 쓰지 않는다면, 그 값을 다룰 수있는 다형 함수를 작성하고 그것을 통해 'T'타입의 데이터를 실행하십시오. 다형 함수는 형식에 의존하지 않는 방법입니다. – AndrewC

답변

6

. 하나는 값이 아니며, 대신 값 중 하나입니다. 두 가지 경우, 이러한 유형은 잘 작동하는 프로그램에는 존재할 수 없습니다. 무한 루프 및 예외 유형에 해당합니다 (예 : 바닥.

마지막으로 이러한 유형은 소유하는 사람이 더 구체적으로 인스턴스를 만들 수 있습니다. 당신이 당신의 함수 호출자에게 그것을주고 있기 때문에 당신이 가지고있는 Int 나 Char를 선택할 수 있다는 것을 의미합니다. 분명히 그건 말이되지 않습니다.

대신 사용자가 원하는 기능의 사용자에게 "이 유형이 무엇인지에 관계없이 작업해야합니다."라고 할 수 있습니다.

foo :: (forall a . a -> r) -> (T -> r) 
foo f (I i) = f i 
foo f (C c) = f c 

당신은 당신이 잘, 다음 모든 유형 정보를 무시하는 함수의 소비자를 강제하는 경우이 기능, 즉 다음

bar :: r -> T -> r 
bar x (I _) = x 
bar x (C _) = x 

정말 유사하게 찾을 수 있습니다, 실제로는 전혀 남아 있지 않습니다 : 예. 상수 함수. 당신이 ExistentialTypes 켜면

+0

사실,'foo' 'f :: (forall a .-> r)'이면'f'가 매개 변수에 의해 상수이기 때문에'bar'보다 훨씬 유용하지 않습니다. 따라서 'I'와 'C'경우를 구분할 수 없습니다. – chi

+0

오, 맞습니다! 전화로 모든 것을 작성해주었습니다. 내가 고칠거야. –

5

당신은 GADTs을 사용할 수 있습니다 : 당신이 아마 원하는 것은 그것이 여러 전선에 잘못 같은 값 (forall a . a)을 반환하지 않습니다

{-# LANGUAGE GADTs #-} 

data T a where 
    I :: Int -> T Int 
    C :: Char -> T Char 

getValue :: T a -> a 
getValue (I i) = i 
getValue (C c) = c 
+0

나는 그것에 대해 생각했다. 그러나 T를 일반 타입 (일명리스트에서 사용)으로 사용하고 매번 새로운 타입을 만들지 않기를 원했다. –

3

, 당신은 쓸 수 있습니다 :

data Anything = forall a. Anything a 

getValue :: T -> Anything 
getValue (I val) = Anything val 
getValue (C val) = Anything val 

그러나이 꽤 쓸모가 없다. (- 그것은 undefined이 될 수 있습니다 아니라, 심지어)가 존재 함을 ...보다

doSomethingWith (Anything x) = ? 

우리는 다른 x에 대해 아무것도 몰라 : 우리는 Anything에 패턴 일치 말. 유형 정보가 없으므로 아무 것도 할 수 없습니다.

+0

감사합니다. 제 질문이 어리 석다는 것을 이해하게 도와주었습니다. –