2013-04-02 52 views
4

在獲得一些幫助之後,理解我試圖編譯代碼的問題,在這個問題中(Trouble understanding GHC complaint about ambiguity)Ness建議我重新設計我的類型類以避免我不完全滿意的解決方案。Haskell類型類的重新設計

有問題的類型類是這些:

class (Eq a, Show a) => Genome a where 
    crossover  :: (Fractional b) => b -> a -> a -> IO (a, a) 
    mutate   :: (Fractional b) => b -> a -> IO a 
    develop   :: (Phenotype b) => a -> b 

class (Eq a, Show a) => Phenotype a where 
    --In case of Coevolution where each phenotype needs to be compared to every other in the population 
    fitness   :: [a] -> a -> Int 
    genome   :: (Genome b) => a -> b 

我試圖創建在Haskell一種可伸縮進化算法,應支持不同GenomesPhenotypes。例如,一個Genome可能是一個位陣列,另一個可能是一個整數列表,而且Phenotypes也可能不同,只是代表部隊運動的雙打列表http://en.wikipedia.org/wiki/Colonel_Blotto,或者它可以代表一個ANN。

由於PhenotypeGenome使用的必須是相當互換的方法開發的,一個Genome類應該能夠通過提供不同的開發方法來支持多個Phenotypes(這可以在代碼中靜態完成,並且沒有在運行時動態完成)。

使用這些類型類的代碼大部分應該是幸福地不知道使用的具體類型,這是什麼導致我問上述問題。

一些,我要適應這些類型類的代碼是:

-- |Full generational replacement selection protocol 
fullGenerational :: (Phenotype b) => 
    (Int -> [b] -> IO [(b, b)]) -> --Selection mechanism 
    Int -> --Elitism 
    Int -> --The number of children to create 
    Double -> --Crossover rate 
    Double -> --Mutation rate 
    [b] -> --Population to select from 
    IO [b] --The new population created 
fullGenerational selection e amount cross mute pop = do 
    parents <- selection (amount - e) pop 
    next <- breed parents cross mute 
    return $ next ++ take e reverseSorted 
      where reverseSorted = reverse $ sortBy (fit pop) pop 

breed :: (Phenotype b, Genome a) => [(b, b)] -> Double -> Double -> IO [b] 
breed parents cross mute = do 
    children <- mapM (\ (dad, mom) -> crossover cross (genome dad) (genome mom)) parents 
    let ch1 = map fst children ++ map snd children 
    mutated <- mapM (mutate mute) ch1 
    return $ map develop mutated 

據我所知,這個代碼將不得不改變,新的限制將被添加,但我想表現我想到的一些代碼使用類型類。例如,上面的全代更換並不需要知道任何關於底層Genome的功能;它只需要知道Phenotypes可以生產Genome,它可以將它們一起繁殖並創建新的孩子。 fullGenerational的代碼應儘可能一般,以便一旦設計了新的Phenotype或創建了更好的Genome,則不需要更改它。

上述類型類如何改變以避免我在類型類模糊性方面遇到的問題,同時保留了我在普通EA代碼中的屬性(應該是可重用的)?

+0

將類型轉換爲等效字典:參見[this](http://www.haskellforall.com/2012/05/scrap-your-type-classes.html)和[this](http:// lukepalmer.wordpress.com/2010/01/24/haskell-antipattern-existential-typeclass/)。 –

+0

@GabrielGonzalez嗯,我可能會誤解,但這將如何幫助解決我模糊不清的問題?我明白,風格可能更清晰,但我不明白如何將我已有的內容轉換爲數據聲明來解決問題。 – Nordmoen

+0

對不起,我誤解了你含糊不清的含義。不理我。 –

回答

7

「它只需要知道的表型可以產生產生它的基因組」

這意味着表型確實出現兩種類型的關係,另一個是基因組類型用於產生一個給定表型:

{-# LANGUAGE MultiParamTypeClasses #-} 
{-# LANGUAGE FunctionalDependencies #-} 

import Data.List (sortBy) 

class (Eq a, Show a) => Genome a where 
    crossover  :: (Fractional b) => b -> a -> a -> IO (a, a) 
    mutate   :: (Fractional b) => b -> a -> IO a 
    develop   :: (Phenotype b a) => a -> b 

class (Eq a, Show a, Genome b) => Phenotype a b | a -> b where 
    -- In case of Coevolution where each phenotype needs to be compared to 
    -- every other in the population 
    fitness   :: [a] -> a -> Int 
    genome   :: a -> b 

breed :: (Phenotype b a, Genome a) => [(b, b)] -> Double -> Double -> IO [b] 
breed parents cross mute = do 
    children <- mapM (\(dad, mom)-> crossover cross (genome dad) (genome mom)) 
        parents 
    let ch1 = map fst children ++ map snd children 
    mutated <- mapM (mutate mute) ch1 
    return $ map develop mutated 

-- |Full generational replacement selection protocol 
fullGenerational :: (Phenotype b a, Genome a) => 
    (Int -> [b] -> IO [(b, b)]) -> --Selection mechanism 
    Int -> --Elitism 
    Int -> --The number of children to create 
    Double -> --Crossover rate 
    Double -> --Mutation rate 
    [b] -> --Population to select from 
    IO [b] --The new population created 
fullGenerational selection e amount cross mute pop = do 
    parents <- selection (amount - e) pop 
    next <- breed parents cross mute 
    return $ next ++ take e reverseSorted 
      where reverseSorted = reverse $ sortBy (fit pop) pop 

fit pop a b = LT -- dummy function 

這個編譯。每種表型will have to provide exactly one implementationgenome

+0

這似乎是我正在尋找。這個答案中唯一缺少的是你在評論中提供的鏈接(http://www.haskell.org/haskellwiki/Functional_dependencies) – Nordmoen

+0

@Nordmoen btw我不記得使用的語言雜注的確切拼寫這裏,心臟;我只是試圖將文件加載到GHCi中,它告訴我哪些選項丟失了。 –

+0

@Nordmoen BTW與Phenotype類定義中的Genome b'約束,兩個函數的約束'Genome a'是多餘的,可以刪除。但它並沒有受到傷害,也許還有其他的文件目的。 –