2012-10-25 3 views
6

왜이 올바른 코드왜이 매개 변수가없는 유형의 인스턴스를 만들 수 없습니까?

instance Functor IO where -- note that IO isn't parametrized, and it's correct 
    fmap f action = do 
     result <- action 
     return (f result) 

하지만 다음 코드는 컴파일러 오류가 무엇입니까?

class Print a where 
    print :: a -> String 

data A t = A t 
instance Print A where -- error: expecting one more argument to `A' 
    print a = "abc" 

답변

10

kinds이 일치하지 않기 때문입니다. 일반 유형은 *이며 A 또는 IO과 같은 유형 생성자는 유형이 * -> *인데 유형을 반환하려면 유형 매개 변수가 필요합니다.

Print 클래스의 정의에서 컴파일러는 a이 일반 유형으로 사용되므로 *이어야합니다. 그러나, 종류 * -> *의 형태 생성자에 Functor 작품 :

여기
class Functor f where 
    fmap :: (a -> b) -> f a -> f b 

, f은 일반 유형으로 사용되지 않지만 타입 생성자로,이 종류의 추론 그래서 * -> *입니다. 당신은 GHCi에서 :kind 명령으로이를 확인할 수 있습니다 :

> :kind Print 
Print :: * -> Constraint 
> :kind Functor 
Functor :: (* -> *) -> Constraint 
9

당신이

class Print a where 
    print' :: a -> String 

당신은 a이 유형으로이 있는지 확인하지만

data A t = A t 

을 말할 때 당신이 A 타입 생성자을 말할 때 - A은 아니다 예를 들어, A Int이 있습니다. A은 형식에 대한 일종의 함수이지만 Print 클래스의 a은 형식 값이 아니고 형식 함수 여야합니다.

당신은 Functor 클래스 타입 생성자를 요구하기 때문에이 IO에 대한 확인이다

instance Print (A Int) where 
    print' a = "abc" 

할 수 있습니다.

class Functor f where 
    fmap :: (a -> b) -> f a -> f b 

당신은 f a는 타입이기 때문에, f 그냥 IOA는 같은 타입 생성자 것을 볼 수 있습니다. 당신은

instance Functor A where -- OK, A is a constructor, Functor needs one 
    fmap f (A x) = A (f x) 

을 할 수있을거야, 그리고 당신이

instance Eq IO where -- not OK - IO is a constructor and Eq needs a type 
    (==) = error "this code won't compile" 

을 할 수 없습니다 (I 표준 기능 print와 충돌하지 않도록 print' 대신 print을 사용했습니다.)

1

인스턴스에서 사용했던 유형 클래스 정의에 주어진 유형의 작성 (또는 텍스트 편집기) 정신적보십시오.에서

:

class Print a where 
    print :: a -> String 

data A t = A t 

우리는, instnace은 우리가 말하고있는 A에 대한 형식 클래스 정의에 a을 대체

instance Print A 

그래서

을 원하는 우리는 이것을 얻었습니다 :

class Print A where 
    print :: A -> String 

어 - 오. A -> String은 유형으로 이해가되지 않습니다. 함수 유형 화살표는 왼쪽에 유형을 입력하고 오른쪽에 유형을 취하고 함수 유형을 제공하기 때문입니다. 그러나 Adata A t으로 A을 선언 했으므로 유형이 아닙니다. A tt 유형의 유형이지만 A유형 생성자입니다. 형식에 적용하면 형식을 만들 수 있지만 A 자체는 다른 형식입니다. 따라서 A tPrint의 인스턴스로 만들 수는 있지만 A 자체는 만들 수 없습니다.

그럼 instance Functor IO은 왜 작동 했습니까? 클래스 정의를 살펴 봅시다 :

class Functor f where 
    fmap :: (a -> b) -> f a -> f b 

지금 f에 대한 IO를 대체하려고 할 수 있습니다 :

class Functor IO where 
    fmap :: (a -> b) -> IO a -> IO b 

IO의 최종 최대 매개 변수를 입력 적용, 그래서 모두가 밖으로 작동합니다. Int 또는 A t과 같은 구체적인 유형을 Functor의 인스턴스로 만들려고하면 문제가 발생합니다.

관련 문제