简体   繁体   English

重新设计Haskell类型

[英]Redesign of Haskell type classes

After getting some help, understanding the problem I had trying to compile the code, in this question ( Trouble understanding GHC complaint about ambiguity ) Will Ness suggested I redesign my type classes to avoid a solution I was not completely happy with. 在得到一些帮助后,理解我试图编译代码的问题,在这个问题中( 麻烦理解GHC关于模糊性的抱怨 )Ness会建议我重新设计我的类型类以避免我不满意的解决方案。

The type classes in question are these: 有问题的类型是这些:

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

I'm trying to create an extendible evolutionary algorithm in Haskell which should support different Genomes and Phenotypes . 我正在尝试在Haskell中创建一个可扩展的进化算法,它应该支持不同的GenomesPhenotypes For instance one Genome could be a bit array, another could be a list of ints, and the Phenotypes will also be diverse from just a list of doubles representing troop movement in http://en.wikipedia.org/wiki/Colonel_Blotto , or it could represent an ANN. 例如,一个Genome可能是一个阵列,另一个可能是一个整数列表, Phenotypes也将不同于一个代表部队运动的双重列表http://en.wikipedia.org/wiki/Colonel_Blotto ,或者它可以代表人工神经网络。

Since a Phenotype is developed from a Genome the methods used must be quite interchangeable, and one Genome class should be able to support multiple Phenotypes by supplying a different develop method (this can be done statically in code, and does not have to be done dynamically at runtime). 由于Phenotype是从Genome开发的,所使用的方法必须是完全可互换的,并且一个Genome类应该能够通过提供不同的开发方法来支持多个Phenotypes (这可以在代码中静态完成,而不必动态完成)在运行时)。

The code using these type classes should, for the most part, be blissfully unaware of the specific types used, which is what lead me to ask the question mentioned above. 在大多数情况下,使用这些类型类的代码应该幸福地不知道所使用的特定类型,这就是让我提出上述问题的原因。

Some of the code that I want to adapt to these type classes are: 我想要适应这些类型类的一些代码是:

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

I understand that this code will have to be changed and new constraints will have to be added, but I wanted to show some of the code I have in mind using the type classes with. 我知道必须更改此代码并且必须添加新的约束,但我想要使用类型类来显示我想到的一些代码。 For instance, the full generational replacement above does not need to know anything about the underlying Genome to function properly; 例如,上面的完整世代替代品不需要知道任何关于底层Genome正常运作; it only needs to know that Phenotypes can produce the Genome that produced it so that it can breed them together and create new children. 它只需要知道Phenotypes可以产生产生它的Genome ,以便它可以将它们一起繁殖并创造新的孩子。 The code for fullGenerational should be as general as possible so that once a new Phenotype is designed or a better Genome is created, it does not need to be changed. fullGenerational的代码应尽可能通用,这样一旦设计了新的Phenotype或创建了更好的Genome ,就不需要更改它。

How can the type classes above be changed to avoid the problems I was/am having with type class ambiguity while retaining the properties I want in the general EA code (which should be reusable)? 如何更改上面的类型类以避免我遇到类型类歧义的问题,同时在一般EA代码中保留我想要的属性(应该是可重用的)?

"it only needs to know that Phenotypes can produce the Genome which produced it " “它只需要知道表型可以产生产生它的基因组”

this means that Phenotype is really a relation on two types, the other being a Genome type used to produce a given Phenotype: 这意味着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

This compiles. 这编译。 Each Phenotype will have to provide exactly one implementation of genome . 每种表型都必须提供一种 genome 实现

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM