2017-02-23 5 views
3

I持って次のコード:私はGHCiの中で次のエラーを取得していますエラートン〜トン - > 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のこのアプリケーションファンクタインスタンスをコンパイルするには、どうすれば実装できますか?

答えて

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 

、1は、より直接的なアプローチを使用することができます私はあなたの答えを読み、 '(<*>)'の署名に 'forall a b.'を追加するまで、InstanceSigs、RankNTypes、ScopedTypeVariablesでも動作するようにはできませんでした。それはなぜ必要なのですか?私は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

ありがとうございました! freenodeの誰かが私にも教えてくれました: インスタンス適用Fooここで 純粋a = Foo a a f <*> a = Foo(field1 f $ field1 a)(field2 f $ field2 a) – MLev

関連する問題