0

데이터 형식에 '숨겨진'(유추 된) 형식과 구체적인 값이 있습니다. 이제는이 두 가지를 변경하는 함수를 구현하려고 시도하지만 GHC를 통과시키지 못합니다.변형 매개 변수화 된 형식 (유추 된 매개 변수 사용)

data T tag val = T val 

data A = A 
data B = B 

mkIntVal :: T a b -> T Int b 
mkIntVal (T x) = T x 

mkCharVal :: T a b -> T Char b 
mkCharVal (T x) = T x 

convert :: T Int a -> T Char b 
convert (T A) = mkCharVal $ T B 
convert (T B) = mkCharVal $ T A 

가 생산하는 오류가 이것이다 :

내 샘플 코드는 이것이다이 작품을 만들기 위해해야할 것에

test.hs:13:12: 
    Couldn't match type `A' with `B' 
    In the pattern: A 
    In the pattern: T A 
    In an equation for `convert': convert (T A) = mkCharVal $ T B 

test.hs:13:17: 
    Couldn't match type `B' with `A' 
    Expected type: T Char b 
     Actual type: T Char B 
    In the expression: mkCharVal $ T B 
    In an equation for `convert': convert (T A) = mkCharVal $ T B 

? 데이터 구조를 변경해야합니까?


내가 다형성 데이터 유형 작업 할 Don Stewart의 솔루션을 확장하기 위해 노력하고

편집 할 수 있습니다.

{-# LANGUAGE MultiParamTypeClasses #-} 
{-# LANGUAGE FunctionalDependencies #-} 
{-# LANGUAGE FlexibleInstances #-} 
{-# LANGUAGE FlexibleContexts #-} 

data C a = C a deriving Show 

class Convertable inVal outVal outTag | outVal -> outTag where 
    convert :: T Int inVal -> T outTag outVal 

instance Convertable A B Char where 
    convert (T A) = mkCharVal $ T B 

instance Convertable B A Char where 
    convert (T B) = mkCharVal $ T A 

instance Convertable a b Char => Convertable (C a) (C (T Char b)) Char where 
    convert (T (C val)) = mkCharVal $ T (C (convert val)) -- line 29 

그러나 그것은 나에게 또 다른 오류 메시지가 있습니다 : 나는 인스턴스 정의와 주위를 연주했지만 가장 유망한가 생각 해낸 찾고 이것이다

test.hs:29:57: 
    Could not deduce (a ~ T Int inVal0) 
    from the context (Convertable a b Char) 
     bound by the instance declaration at test.hs:28:10-70 
     `a' is a rigid type variable bound by 
      the instance declaration at test.hs:28:22 
    In the first argument of `convert', namely `val' 
    In the first argument of `C', namely `(convert val)' 
    In the first argument of `T', namely `(C (convert val))' 

돈은 그것이 있어야 말했듯을 가능한 구현 방법에 관심이 있습니다.


훨씬 더 '재생'후 솔루션

나는 마지막으로 작동 뭔가를 내놓았다. 이게 너에게 잘 보이니?

{-# LANGUAGE MultiParamTypeClasses #-} 
{-# LANGUAGE FunctionalDependencies #-} 
{-# LANGUAGE FlexibleContexts #-} 
{-# LANGUAGE FlexibleInstances #-} 
{-# LANGUAGE UndecidableInstances #-} 
{-# LANGUAGE OverlappingInstances #-} 


data T tag val = T val deriving Show 

data A = A deriving Show 
data B = B deriving Show 
data C a = C a deriving Show 


class Convertable inTag inVal outTag outVal | inTag -> outTag, inVal -> outVal 
where 
    convert :: T inTag inVal -> T outTag outVal 

instance Convertable Int A Char B where 
    convert (T A) = T B 

instance Convertable Int B Char A where 
    convert (T B) = T A 

instance (Convertable Int (T Int a) Char (T Char b), Convertable Int a Char b) 
    => Convertable Int (C (T Int a)) Char (C (T Char b)) where 
    convert (T (C x)) = T (C (convert x)) 

instance Convertable Int (C (T Int A)) Char (C (T Char B)) where 
    convert (T (C x)) = T (C (convert x)) 

instance Convertable Int (C (T Int B)) Char (C (T Char A)) where 
    convert (T (C x)) = T (C (convert x)) 

사용법 :

*Main> convert $ mkIntVal $ T $ C $ mkIntVal $ T A 
T (C (T B)) 
*Main> :t it 
it :: T Char (C (T Char B)) 

답변

1
당신의 convert 기능의 각 케이스는 다른, 충돌 유형이

:

convertA :: T t A -> T Char B 
convertA (T A) = mkCharVal $ T B 

convertB :: T t B -> T Char A 
convertB (T B) = mkCharVal $ T A 

당신이하는 typeclass를 통해 이들을 통합 할 수

{-# LANGUAGE MultiParamTypeClasses #-} 
{-# LANGUAGE FunctionalDependencies #-} 


class C a b c | b -> c where 
    convert :: T t a -> T c b 

instance C A B Char where 
    convert (T A) = mkCharVal (T B) 

instance C B A Char where 
    convert (T B) = mkCharVal (T A) 

서로 다른 유형의 하나의 기능이 다른 방향으로 변환되기를 바랍니다. 이 방법을 사용하여 태그가있는 T을 가져 와서 버리고 태그와 값을 값 유형에 따라 결정된 새 태그로 바꿉니다.

+0

이제 내 시도가 잘못되었다는 것을 이해합니다. 나중에이 솔루션을 다형성 결과 유형으로 확장하거나 "일반"유형으로 제한 할 수 있습니까? 인스턴스 정의에 넣을 구체적인 값이 없기 때문에'convert (T (C val)) = mkCharVal $ T (C (convert val))와 같은 함수를 어떻게 만들지 모르겠다. ' –

+0

가능해야합니다. 시도 해봐! –

관련 문제