使用FlexibleContexts和FlexibleInstances有哪些缺陷? [英] What are the pitfalls of using FlexibleContexts and FlexibleInstances?

查看:200
本文介绍了使用FlexibleContexts和FlexibleInstances有哪些缺陷?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于这些灵活的上下文和实例在Haskell标准中不可用,我假设在使用它们时存在潜在的问题。他们是什么?它们能导致一些含糊不清,重叠的实例等吗?



有一个类似的问题,只询问 FlexibleInstances ,而不是 FlexibleContexts ,但答案只是说这是安全的使用它们。

解决方案

我曾经偶然发现了以下情况。 回答这个问题,我第一次尝试这个代码:



<$ p $
{ - #LANGUAGE MultiParamTypeClasses# - }
{ - #LANGUAGE FunctionalDependencies# - }
$ b $ class(Eq a,Show a)=>基因组a其中
crossover ::(小数b)=> b - > a - > a - > IO(a,a)
mutate ::(Fractional b)=> b - > a - > IO a
develop ::(表型b a)=> a - > b

class(Eq a,Show a)=>表型a b | a - > b其中
- 在Coevolution的情况下,每个表型需要与
相比较 - 在​​人口中每隔一个
fitness :: [a] - > a - > Int
genome ::(Genome b)=> a - > b - 在这里,问题

繁殖父母交叉静音= do
children < - mapM(\(爸爸,妈妈) - >交叉交叉(基因组爸爸)(基因组妈妈))
父母
let ch1 = map fst children ++ map snd children
mutated< - mapM(mutate mute)ch1
return $ map开发变异

得到一个编译错误和GHCi建议添加 FlexibleContexts 选项。当我这样做,它编译好。但是这实际上不是一件正确的事情,因为约束声明为类型变量引入了新的范围,并且在基因组 b c>的类型签名变得与类型类中的完全无关;但 FlexibleContexts 为此提供了掩护。



在类型级别指定适当的约束时,

 类(等式a,显示a,基因组b)=>表型a b | a  - > b其中
- 在Coevolution的情况下,每个表型需要与
相比较 - 在​​人口中每隔一个
fitness :: [a] - > a - > Int
genome :: a - > b

它通过编译而不需要 FlexibleContexts 选项。

Since these flexible contexts and instances aren't available in the Haskell standard, I assume there are potential problems when using them. What are they? Can they lead to some ambiguity, undecidability, overlapping instances, etc.?

There is a similar question that asks only about FlexibleInstances, not FlexibleContexts, but the answer only says "that it's safe to use them".

解决方案

I once stumbled upon the following. Answering this question, I first tried this code:

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

And got a compilation error and a suggestion by GHCi to add the FlexibleContexts option. When I did, it compiled OK. But this was actually not a right thing to do, as the constraint declaration introduced new scope for type variables, and b in genome's type signature became completely unrelated to the one in the type class; yet FlexibleContexts provided a cover for this.

With the constraint specified properly at the type class level,

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

it passed compilation without requiring the FlexibleContexts option.

这篇关于使用FlexibleContexts和FlexibleInstances有哪些缺陷?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆