2017-02-23 6 views
3

나는이 다음 코드 : 나는 GHCi에서 다음과 같은 오류가 점점 오전오류 t ~ t -> T1

{-# LANGUAGE DeriveFunctor #-} 

data Foo a = Foo { field1 :: a, field2 :: a} deriving (Functor) 

instance Applicative Foo where 
    pure a = Foo a a 
    f <*> a = Foo (r field1) (r field2) 
    where r g = g f $ g a 

:

help.hs:8:23: error: 
    • Occurs check: cannot construct the infinite type: t ~ t -> t1 
    • In the second argument of ‘($)’, namely ‘g a’ 
     In the expression: g f $ g a 
     In an equation for ‘r’: r g = g f $ g a 
    • Relevant bindings include 
     g :: Foo (a -> b) -> t -> t1 (bound at help.hs:8:13) 
     r :: (Foo (a -> b) -> t -> t1) -> t1 (bound at help.hs:8:11) 

help.hs:8:25: error: 
    • Couldn't match type ‘a’ with ‘a -> b’ 
     ‘a’ is a rigid type variable bound by 
     the type signature for: 
      (<*>) :: forall a b. Foo (a -> b) -> Foo a -> Foo b 
     at help.hs:7:5 
     Expected type: Foo (a -> b) 
     Actual type: Foo a 
    • In the first argument of ‘g’, namely ‘a’ 
     In the second argument of ‘($)’, namely ‘g a’ 
     In the expression: g f $ g a 
    • Relevant bindings include 
     g :: Foo (a -> b) -> t -> t1 (bound at help.hs:8:13) 
     r :: (Foo (a -> b) -> t -> t1) -> t1 (bound at help.hs:8:11) 
     a :: Foo a (bound at help.hs:7:9) 
     f :: Foo (a -> b) (bound at help.hs:7:3) 
     (<*>) :: Foo (a -> b) -> Foo a -> Foo b (bound at help.hs:7:3) 

어떻게 Foo의이 적용 가능한 Functor 인스턴스를 구현하여 컴파일 할 수 있습니까?

답변

4

r g = g f $ g a 

다형성 함수로 g 필요한 정의 - GHC 이러한 복합 타입을 추론 할 수 없다.

당신은 당신이 정말로 당신의 코드를 컴파일하려면, 당신의 유형에 더 명시해야합니다

instance Applicative Foo where 
    pure a = Foo a a 
    (Foo f1 f2) <*> (Foo a1 a2) = Foo (f1 a1) (f2 a2) 
+0

뭔가를 시도했다 : 또는

{-# LANGUAGE ScopedTypeVariables, DeriveFunctor, InstanceSigs, Rank2Types #-} instance Applicative Foo where pure a = Foo a a (<*>) :: forall a b. Foo (a->b) -> Foo a -> Foo b f <*> a = Foo (r field1) (r field2) where r :: (forall t. Foo t -> t) -> b r g = g f $ g a 

, 하나는 더 직접적인 방법을 사용할 수 있습니다 이런 식으로 InstanceSigs, RankNTypes, ScopedTypeVariables를 사용해도 대답을 읽을 수없고'(a)'에 대한 서명에 forall a b를 추가 할 때까지는 작동하지 않습니다. 왜 그게 필요한가요? 나는 RankNTypes에 대해 꽤 경험이 없지만'forall a b '가 거기에 내재되어있을 것으로 기대했다. – amalloy

+0

@amalloy 이것은 IMO, 하스켈의 원래 정의에서의 실수이다.'let f :: a -> ...; f = ... 여기서 g :: a -> ...'는 실제로'let f :: forall a1을 의미합니다. a1 -> ...; f = ... 여기서 g :: forall a2. a2 -> ...'. 예, 가장 안쪽의'a'는 국부적으로 정량화되어 있으며, 가장 바깥 쪽의 것과는 관계가 없습니다. 하스켈 보고서를 연설했습니다. GHC는 현재 비표준'forall a. 표준 준수 코드를 깨지 않고 안전하게 표준에서 벗어날 수 있습니다. – chi

+0

감사합니다. @chi! freenode의 누군가도 나를 줬다 : 인스턴스 적용 Foo 어디 순수 a = Foo a a f <*> a = Foo (field1 f $ field1 a) (field2 f $ field1 a) – MLev