Как обойти условие покрытия для функциональных зависимостей без использования -XUndecidableInstances - PullRequest
5 голосов
/ 31 января 2012

Используя функциональные зависимости, я часто сталкиваюсь с условием покрытия .Можно поднять его с помощью UndecidableInstances, но я обычно стараюсь держаться подальше от этого расширения.

Вот несколько надуманный пример, который работает без UndecidableInstances:

{-# Language MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances #-}

data Result = Result String
  deriving (Eq, Show)

data Arguments a b = Arguments a b

class Applyable a b | a -> b where
  apply :: a -> b -> Result

instance Applyable (Arguments a b) (a -> b -> Result) where
  (Arguments a b) `apply` f = f a b

Когда я делаю тип результата более общим, условие покрытия не выполняется (следовательно, требуется UndecidableInstances):

{-# Language MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, UndecidableInstances #-}

data Result a = Result a
  deriving (Eq, Show)

data Arguments a b = Arguments a b

class Applyable a b c | a -> b c where
  apply :: a -> b -> Result c

instance Applyable (Arguments a b) (a -> b -> Result c) c where
  (Arguments a b) `apply` f = f a b

Я думал, что, поскольку b и c оба определяются a,более общий код не должен вызывать проблем, поэтому мои вопросы:

  1. Есть ли возможные проблемы с использованием UndecidableInstances здесь
  2. Могу ли я смоделировать описанный выше сценарий, не полагаясь на UndecidableInstances (может быть с типами семей?)

1 Ответ

7 голосов
/ 21 марта 2012

Нет большой причины держаться подальше от UndecidableInstances.Худшее, что может случиться, это то, что средство проверки типов начинает зацикливаться (и, я думаю, говорит вам об этом).Вы можете сделать условие покрытия все более и более умным, но оно никогда не сделает все, что вы хотели, так как это неразрешимо.

...