2013-06-13 16 views
8

Próbuję napisać prosty algorytm genetyczny w Haskell. Pomyślałem, pierwszym krokiem powinno być dokonać typeclass dla osób, które są „genetyczne”, tak:Korzystanie z najbardziej ogólnych typów funkcji typeclass

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

To wydaje mi się rozsądne - nie koniecznie chcą, aby ograniczyć funkcje przydatności do określonego typu jak Float lub konceptualnie wszystkie funkcje fitness powinny zapewniać zamawianie osób.

Jednak, kiedy wdrożyć ten typeclass dla String Wrapper:

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

widzę następujący błąd w GHC:

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

czy nie jest to w jaki sposób należy określić funkcje typeclass? Czy muszę ograniczyć funkcję do określonego typu betonu lub podać inną zmienną typu do konstruktora typeclass?

+7

Jest to powszechny problem. Twój podpis oznacza, że ​​* osoba dzwoniąca * może wybrać rodzaj zamówienia, więc 'fitness' musi być w stanie wyprodukować wartość dowolnego typu do zamówienia i zwrócić ją. Uwaga: 'Void' (typ bez wartości) jest uporządkowany, więc jest to niemożliwe. Prawdopodobnie chcesz sparametryzować 'Genetic' na przestrzeni zamówienia:' class (Ord b) => Genetic b a where fitness :: a -> b' – luqui

+0

@luqui Dzięki, myślę, że dostaję to. Próbując tego, wydaje się, że waniliowy Haskell nie lubi wieloparametrowych typów czcionek. Kto by pomyślał. –

+1

@DanielBuckmaster Tak, ale rozszerzenie 'MultiParamTypeclasses' jest dość powszechne w użyciu – jozefg

Odpowiedz

13

Luqui wyjaśnił na czym polega problem: fitness musiałby być w stanie zapewnić żadnegoOrd instancji rozmówca może żądać, kiedy to, co naprawdę chcesz to jakiś specyficzny że pasuje rodzaj najlepszą.

To jest IMO bardzo miłe dla aplikacji związanych synonimami typu:

{-# 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

Och, wow, to jest fajne. Myślę, że mógłbym po prostu iść tą drogą. Dzięki! –

+0

Z wyjątkiem, otrzymuję komunikat o błędzie: "Zmienna typu zmienna typu w ograniczeniu: Ord (Fitness a)'. Mówi się "(użyj opcji -XFlexibleContexts, aby na to pozwolić)" - brzmi jak wymagana jest inna pragma? –

+3

@ Daniel Copuckmaster, tak, przygotuj się na rozszerzenie, które kompilator zaleca w tym momencie. Kod Typeclass czasami jest podobny ... – luqui

Powiązane problemy