由于这些灵活的上下文和实例在 Haskell 标准中不可用,我假设使用它们时存在潜在问题。这些是什么?它们会导致一些歧义、不可判定性、重叠实例等吗?
有一个类似的问题只询问FlexibleInstances
,而不是FlexibleContexts
,但答案只说“使用它们是安全的”。
由于这些灵活的上下文和实例在 Haskell 标准中不可用,我假设使用它们时存在潜在问题。这些是什么?它们会导致一些歧义、不可判定性、重叠实例等吗?
有一个类似的问题只询问FlexibleInstances
,而不是FlexibleContexts
,但答案只说“使用它们是安全的”。
我曾经偶然发现以下内容。回答这个问题,我首先尝试了这段代码:
{-# 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
ingenome
的类型签名与类型类中的签名完全无关;但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
选项。