2014-04-15 4 views
9

나는폐쇄 형 패밀리에 대한 제약 조건은 무엇입니까?

pretty :: Text -> Text = id 
pretty :: String -> Text = T.pack 
pretty :: (Show a) => a -> Text = T.pack . show 

그래서 아이디어는 이미 Show 인스턴스가 아무것도 설정 할 수 있다는 것입니다

pretty :: (Show a) => a -> Text 

같은 유형의 함수의 끔찍하게 비모수 버전을 쓰고 싶습니다 Text에 의해서만 -ing하고 있습니다. 단, TextString을 제외하고는 특별한 경우가 있습니다.

{-# LANGUAGE TypeFamilies #-} 
{-# LANGUAGE MultiParamTypeClasses #-} 
{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, FlexibleContexts #-} 
{-# LANGUAGE DataKinds, ConstraintKinds #-} 
module Pretty (pretty) where 

import Data.Text (Text) 
import qualified Data.Text as T 

type family StringLike a :: Bool where 
    StringLike String = True 
    StringLike Text = True 
    StringLike a = False 

class (b ~ StringLike a) => Pretty' a b where 
    pretty' :: a -> Text 

instance Pretty' String True where 
    pretty' = T.pack 

instance Pretty' Text True where 
    pretty' = id 

instance (Show a, StringLike a ~ False) => Pretty' a False where 
    pretty' = T.pack . show 

type Pretty a = (Pretty' a (StringLike a)) 

pretty :: (Pretty a) => a -> Text 
pretty = pretty' 

과는 pretty 기능을 제외하고 아무것도 내 보내지 않고 사용할 수 있습니다

다음 코드는 작동합니다.

그러나, 나는 pretty의 유형 서명에 대해 너무 행복하지 않다 :

pretty :: (Pretty a) => a -> Text 

내가 StringLike는 폐쇄 형 가족이기 때문에, GHC 알아낼 수있는 방법이 있어야한다고 생각 만 (Show a) 경우

1. The following hold trivially just by substituting the results of applying StringLike: 
(StringLike String ~ True, Pretty' String True) 
(StringLike Text ~ True, Pretty' Text True) 

2. For everything else, we *also* know the result of applying StringLike: 
(Show a, StringLike a ~ False) => (Pretty' a (StringLike a)) 

이의 GHC를 설득 할 수있는 방법이 있나요 : 이후, (Pretty a) 이미 만족, 보유?

+0

'Prelude' 자격을 가져오고'Pretty'의 이름을'Show'로 변경하는 'ha-ha just serious'아이디어가 나에게 발생했습니다 ... – Cactus

+2

"StringLike가 닫힌 타입의 패밀리이기 때문에 GHC가 (Show a)만이 보유하고있는 경우"다음과 같은 것이 큰 문제라고 생각합니다. StringLike는 일종의 종류를 산출합니다. (-lifted)'Bool','Show'는 일종의'Constraint' 타입을 산출합니다. GHC가 그 관계를 이해하지 못하는 것은 아닙니다. 그들은 실제로 다른 논리의 법칙을 따른다. Bool이 해제되면, 제외 된 중간의 법칙을 가정하지만, Constraint를 사용하면 그 법칙에 의존하지 않을 수 있습니다. –

답변

5

나는 StringLike는 폐쇄 형 가족이기 때문에, GHC는 (Show a)가 보유하고있는 경우, (Pretty a)

그 유형 검사를 요구하려면 이미 만족하고 있음을 알아낼 수있는 방법이 있어야한다고 생각 , 매개 변수 다형성을 깨뜨릴 것입니다. 당신의 인수로 이제 형 가족

type family IsInt a :: Bool where 
    IsInt Int = True 
    IsInt a = False 
class (b ~ IsInt a) => TestInt a b where 
    isInt :: a -> Bool 
instance TestInt Int True where 
    isInt _ = True 
instance (IsInt a ~ False) => TestInt a False where 
    isInt _ = False 

을 정의 고려, GHC는 ()에서 TestInt a를 충족 할 수 있어야한다. 즉, Int와 동일한 지 여부를 테스트 할 수 있어야합니다. 이것은 분명히 불가능합니다.

마찬가지로, Show a 사전은 a -> ShowS과 같습니다. 그 인수가 StringLike인지 여부를 어떻게 결정할 수 있습니까?

+1

"즉, 주어진 유형에 대해 'Int'와 같은지 테스트 할 수 있어야합니다. 이것은 분명히 불가능합니다." 그렇지? 우리는 이미 예를 들어 이것을 필요로하지 않습니다. 유형 통일? 내가 여기서 무엇을 놓치고 있니? –

+0

그래서 기본적 점은 우리는'증명 (나타 내기) 할 수 있다는 것입니다 => (꽤) ', 어떤 의미에서, 비 건설적으로? – Cactus

+0

http://hackage.haskell.org/package/base-4.7.0.0/candidate/docs/Data-Type-Equality.html#t--61--61-에서 'IsInt'가 이미 가능하지 않습니까? – copumpkin

2

아마도 내가 당신의 목표를 오해했을 수도 있지만, 이것은 당신이 원하는 유형을 얻으려는 많은 노력처럼 보입니다. 이 pretty가, 인해 IncoherentInstances를 입력 Pretty a => a -> Text을 가져야한다고 보일 수도 있지만

{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, UndecidableInstances, IncoherentInstances #-} 
module Prettied where 

import Data.Text (Text, pack) 

class Pretty a where pretty :: a -> Text 

instance   Pretty Text where pretty = id 
instance   Pretty String where pretty = pack 
instance Show a => Pretty a  where pretty = pack . show 

실제로 유형 Show a => a -> Text이있을 것이다. IncoherentInstances을 사용하면 유효한 코드를 해독 할 수있는 기능 중 하나이기 때문에이 모듈이 자체 모듈에 있어야합니다.

+6

나는 IncoherentInstances를 사용하지 말 것을 강력히 권고한다. 이 정의를 사용하면''pretty "foo"'가''foo ''가됩니다. 그러나'pretty2 x = pretty x'를 추가하면'pretty2 "foo"'는''\ "foo \" "'가됩니다. 별로 강건하지도 예측할 수도 없습니다. – kosmikus

+2

네, 목표는'IncoherentInstances' 또는'UndecideableInstances' 같은 더러운 물건없이이 작업을 수행하는 것입니다. – Cactus

+3

그냥 'OverlappingInstances'가 작동합니다. 나는 우리가 단지 우리가 폐쇄 형 가족과 함께 갈 수있는 기능 수준의 아날로그가없는 어색한 단계의 비트에 있다고 생각, 그래서 우리는 비교적 쉽게 사물의 이러한 종류를 정의 할 수 있지만 (에 타입 클래스를 사용하여이있는 우리는 닫을 수 없습니다.), OverlappingInstances, UndecidableInstances 등 – jberryman

관련 문제