Ответ 1
Я однажды наткнулся на следующее. Отвечая на этот вопрос, я сначала попробовал этот код:
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
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) => 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 :: (Genome b) => a -> b -- here, the problem
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
И получил ошибку компиляции и предложение GHCi добавить параметр FlexibleContexts
. Когда я это сделал, он скомпилировался ОК. Но на самом деле это было неправильно, поскольку объявление ограничения вводило новую область для переменных типа, а подпись типа b
в genome
стала полностью не связана с таковой в классе типа; но FlexibleContexts
обеспечил покрытие для этого.
Если ограничение задано правильно на уровне класса типа,
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
он передал компиляцию, не требуя опции FlexibleContexts
.