繁体   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