2013-06-13 12 views
8

私はHaskellで単純な遺伝的アルゴリズムを書こうとしています。私は、最初のステップは、「遺伝的」であり、個人のための型クラスを作るので、好きにする必要があります考え出し:最も一般的なtypeclass関数型を使用する

class Genetic a where 
    fitness :: (Ord b) => a -> b 

これは私には合理的なようだ - 私は必ずしもFloatのようなタイプに適応機能を制限しませんまたはDoubleであり、概念的にすべてのフィットネス機能は、個人の発注を提供する必要があります。

しかし、私はStringラッパーのこの型クラスを実装する場合:

data DNA = DNA String 
instance Genetic DNA where 
    fitness (DNA s) = length s 

私はGHCに次のエラーを参照してください。

Could not deduce (b ~ Int) 
from the context (Ord b) 
    bound by the type signature for fitness :: Ord b => DNA -> b 

が、これは私が型クラスの関数を定義する方法はないですか?関数を特定の具体的な型に限定しなければならないのですか、型のコンストラクタに別の型の変数を与える必要がありますか? fitnessに何が本当にしたいことはタイプ最高に合ったいくつかの特定のものであるとき、発信者は、要求する可能性のあるOrdインスタンスを提供できるようにする必要があります:

+7

これは共通の問題である:

これは、IMO関連するタイプの同義語のための非常に素晴らしいアプリケーションです。あなたの署名は*発呼者*が発注可能なタイプを選択することを意味するので、 'fitness'は発注可能なタイプの値を作り、それを返すことができなければなりません。 「Void」(値のない型)は注文可能なので、これは不可能です。注文空間で 'Genetic'をパラメータ化したいと思うかもしれません:' class(Ord b)=> Genetic b a fitness :: a - > b' – luqui

+0

@luquiありがとう、私はそれを得ると思います。それを試してみると、バニラ・ハスケルはマルチタイプパラメータの型式が気に入らないようです。誰が考えていたでしょうか。 –

+1

@DanielBuckmasterはい、 'MultiParamTypeclasses'拡張はかなり一般的です。 – jozefg

答えて

13

Luquiは、問題が何であるかを説明しました。

{-# LANGUAGE TypeFamilies, FlexibleInstances, FlexibleContexts #-} 

class (Ord (Fitness a)) => Genetic a where 
    type Fitness a :: * 
    fitness :: a -> Fitness a 

data DNA = DNA String 
instance Genetic DNA where 
    type Fitness DNA = Int 
    fitness (DNA s) = length s 
+0

ああ、それは素晴らしいです。私はちょうどこのように行くかもしれないと思う。ありがとう! –

+0

例外を除いて、私はエラーが発生しました: '制約の中の非可変引数:Ord(Fitness a)'。 '(これを許可するには-XFlexibleContextsを使用する)'と言っています - 別のプラグマが必要なように聞こえますか? –

+3

@DanielBuckmaster、ええ、この時点でコンパイラが推奨する拡張モジュールを用意する準備ができています。 Typeclassコードは時々そうです... – luqui

関連する問題