2015-10-14 16 views
6

私は型(Aと呼ぶ)を持っていて、A型 - > A型 - > A型の関数の型定義をしたい。 - > A、A - > A - > A - > ...などこれは動作しません:Haskell - A型のすべての関数 - > A - > ... - > A

{-# LANGUAGE FlexibleInstances #-} 

data A = A 

class AsToA a where 
    takeA :: AsToA b => a -> A -> Either A b 

instance AsToA (A -> A) where 
    takeA f a = Left (f a) 

instance AsToA b => AsToA (A -> b) where 
    takeA f a = Right (f a) 

私は、次のエラーメッセージが出ます:

AsToA.hs:12:22: 
    Couldn't match expected type ‘b1’ with actual type ‘b’ 
     ‘b’ is a rigid type variable bound by 
      the instance declaration at AsToA.hs:11:10 
     ‘b1’ is a rigid type variable bound by 
      the type signature for 

      takeA :: AsToA b1 => (A -> b) -> A -> Either A b1 
      at AsToA.hs:12:3 
    Relevant bindings include 
     f :: A -> b (bound at AsToA.hs:12:9) 
     takeA :: (A -> b) -> A -> Either A b1 (bound at AsToA.hs:12:3) 
    In the first argument of ‘Right’, namely ‘(f a)’ 
    In the expression: Right (f a) 

任意のアイデア?何かアドバイスをありがとうございました。 2つのb sの間にいくつかの混乱がある

+0

私はtakeA'が暗黙的存在量化された 'からだと90%確信しています。 –

答えて

2

他の回答にコメントで述べたように、あなたは本当にEitherを必要としないかもしれません、とtakeAはちょうどタイプの制限で、基本的には常に、その後idです。あなたは、このメソッドレスクラスにすることができた場合:

{-# LANGUAGE FlexibleInstances, FlexibleContexts #-} 

data A = A 

class AsToA a 

takeA :: AsToA a => a -> a 
takeA = id 

instance AsToA (A -> A) 

instance AsToA (A -> b) => AsToA (A -> (A -> b)) 

また、あなたが動的にA秒で通過することを可能にする共通の型に機能を変換したい場合があります。そうEitherが十分ではありませんが、あなたがあなた自身を定義することができた場合:

{-# LANGUAGE FlexibleInstances, FlexibleContexts #-} 

data A = A 

data R = Result A | MoreArgs (A -> R) 

class AsToA a where 
    takeA :: a -> A -> R 

instance AsToA (A -> A) where 
    takeA f a = Result (f a) 

instance AsToA (A -> b) => AsToA (A -> (A -> b)) where 
    takeA f a = MoreArgs (takeA $ f a) 
+0

その2番目の答えは完璧です、ありがとう。私が以前にはっきりしていなかったのならば、すみません。 – RhubarbAndC

4

class AsToA a where 
    takeA :: AsToA b => a -> A -> Either A b 

instance AsToA b => AsToA (A -> b) where 
    takeA f a = Right (f a) 

これらは同じではありません。さんは今

class AsToA a where 
    takeA :: AsToA c => a -> A -> Either A c 

instance AsToA b => AsToA (A -> b) where 
    takeA f a = Right (f a) 

cへの最初の名前を変更してみましょう、 Right (f a)Either A bを入力しますが AsToA cが成立するように任意の c用タイプ Either A cを持っている必要があります。これは型チェックを行いません。ここ

問題があることtakeA任意のc、発信者の選択のためEither A cを返すことができるという署名

takeA :: AsToA c => a -> A -> Either A c 

約束。これはあなたが望むものではありません。


実際の意図した結果はまだわかりませんが、問題は次のようになります。種類の機能f考える

タイプの各->ため xの1つの適用(従ってタイプA->Aの)と、関数 \x -> f x x ...を返すA->A->...->A

可能な解決策は、これは非常にであり、使用するOverlappingInstancesを必要とすること

{-# LANGUAGE FlexibleInstances, OverlappingInstances #-} 
data A = A -- could be anything 

class C f where 
    takeA :: f -> A -> A 

instance C (A -> A) where 
    takeA f = f 

instance C b => C (A -> b) where 
    takeA f = \x -> takeA (f x) x 

注あります。私はそれを避けることをお勧めします。

これを避けるには、 タイプのAの場合でもインスタンスを定義すれば十分です。

{-# LANGUAGE FlexibleInstances #-} 
data A = A -- could be anything 

class C f where 
    takeA :: f -> A -> A 

instance C A where 
    takeA a = \_ -> a 

instance C b => C (A -> b) where 
    takeA f = \x -> takeA (f x) x 
+1

* takeAは任意のc *に対してA cを返すことができることを約束します.-本質的に、 'takeA'が' forall bとして宣言されているという問題です。 AsToA b = a - > a - > A b'の場合、ここでは 'b'は剛体です。 –

+0

だから私は何を提案しますか?このtypeclassをまったく定義することは可能ですか? – RhubarbAndC

+1

@RhubarbAndC私はあなたが何を必要としているのかわかりません –

関連する問題