簡體   English   中英

重新設計Haskell類型

[英]Redesign of Haskell type classes

在得到一些幫助后,理解我試圖編譯代碼的問題,在這個問題中( 麻煩理解GHC關於模糊性的抱怨 )Ness會建議我重新設計我的類型類以避免我不滿意的解決方案。

有問題的類型是這些:

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 ,或者它可以代表人工神經網絡。

由於Phenotype是從Genome開發的,所使用的方法必須是完全可互換的,並且一個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代碼中保留我想要的屬性(應該是可重用的)?

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

這意味着Phenotype實際上是兩種類型的關系,另一種是用於產生給定表型的基因組類型:

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

這編譯。 每種表型都必須提供一種 genome 實現

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM