Подтвердить что ты не робот

Каковы подводные камни использования FlexibleContexts и FlexibleInstances?

Поскольку эти гибкие контексты и экземпляры недоступны в стандарте Haskell, я предполагаю, что при их использовании существуют потенциальные проблемы. Кто они такие? Могут ли они привести к некоторой двусмысленности, неразрешимости, перекрывающимся экземплярам и т.д.?

Существует аналогичный вопрос который запрашивает только FlexibleInstances, а не FlexibleContexts, но ответ только говорит "что он безопасен для их использования" .

4b9b3361

Ответ 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.