2013-06-17 2 views
7

오늘 유형 유형의 데이터를 저장하지 않고 다른 유형의 데이터를 저장하는 것과 같은 방식으로 데이터 유형을 구성 할 수 있는지 조사하고 싶었습니다. . 그래서 여기에 a 타입의 타입 생성자를 가지고 있지만 ByteString 타입의 데이터 생성자를 가진 GADT에 대한 나의 시도가 있습니다.유형 제한이있는 GADT의 Functor 인스턴스

decode' :: (Serialize a) => Serialized a -> a 
decode' (MkSerialized bs) = let Right r = (decode bs) in r 

을 그리고 그것은 작동합니다 :

{-# LANGUAGE GADTs #-} 
import Data.ByteString.Char8 
import Data.Serialize 

data Serialized a where 
    MkSerialized :: (Serialize a) => ByteString -> Serialized a 

지금 나는 다음과 같은 방법으로 decode' 기능을 정의 할 수 있습니다

let s = MkSerialized (encode "test") :: Serialized String 
print $ decode' s  -- prints "test" 

내 문제는 내가가 될 Serialized을하고 싶은 것이 지금 Functor의 인스턴스

하지만 (Serialize b) 오류가 발생합니다. 어떻게 Serializefmap에 적용되도록 Functor 인스턴스를 제한 할 수 있습니까?

+2

수 없습니다. 'Functor'는 타입 파라미터에 대한 제약 조건을 요구하지 않습니다. 'rmonad' 패키지에는 제한된 Functor 클래스가 있습니다. ['RFunctor'] (http://hackage.haskell.org/packages/archive/rmonad/0.8/doc/html/Control-RMonad.html#t:RFunctor) . 어쩌면 당신이 그것을 사용할 수 있습니다. –

+2

이것은 당신의 질문과 관련이 없습니다 - 이것은 실제로'Functor'에서 가능하지 않습니다 - 그러나 나는 의무적으로 말합니다 :'Data.ByteString.Char8'을 디폴트로 사용하지 마십시오! 깨진 코드를 깨뜨린 모듈입니다. 때로는 일부 용도가 있지만 코드가 유니 코드의 오해를 조장하지 않는'Data.ByteString'과 함께 작동합니다. – shachaf

+1

그게 무슨 가치가 있는지, 당신은'CoYoneda' 스타일의 데이터 타입을 만들 수 있습니다'data Serialized a MkSerialized :: Serialize x => ByteString -> (x -> a) -> Serialized a' ByteString과 a post-deserialization 함수를 가지고 있고, Functor 인스턴스를 가지고있다. 그러나 당연히 여기의 목적을 저지합니다. – shachaf

답변

6

CoYoneda functor을 사용하면됩니다.

아이디어는 간단합니다. fmap 기능을 누적하는 추가 기능 필드가 있습니다. 가치를 해독 할 때 그 기능을 적용하십시오. 귀하의 경우에있을 것 같은

{-# LANGUAGE GADTs #-} 
import Data.ByteString.Char8 
import Data.Serialize 

data Serialized a where 
    MkSerialized 
     :: (Serialize a) 
     => ByteString -> (a -> b) -> Serialized b 

decode' :: Serialized a -> a 
decode' (MkSerialized bs f) = let Right r = decode bs in f r 

instance Functor Serialized where 
    fmap f (MkSerialized bs g) = MkSerialized bs (f . g) 

이 자동으로 여러 fmap의 대신 반복 decodings 및 인코딩 융합의 혜택이 있습니다

여기에 코드입니다.

+2

이것은 실제로 내 문제를 해결하지는 않지만 (반복되는 인코딩/인코딩을 수행하기 위해'fmap '을 좋아했기 때문에) 나는이 대답을 받아 들일 것이다. b/c 나는 나의 원래 생각이 가능하지 않다는 것을 안다. 제한된 GADT에 대한 펑터를 정의하는 가장 실용적인 방법입니다. 또한 [GADT 및 Yoneda 펑 터에 대한 흥미로운 읽기] (http://www.haskellforall.com/2012/06/gadts.html). – Phae7rae