Не могу вывести суперкласс

В следующем коде GHC не может найти экземпляр Functor в определении экземпляра Monoidal.

Почему GHC не делает вывод, что данное ограничение Applicative выполнено, то Functor должно где-то уже быть? (Есть ли название для этой «способности» рассуждения?)

import Prelude hiding (Applicative (..), Monad (..))

class Functor f => Applicative f where
  pure :: a -> f a
  (<*>) :: f (a -> b) -> f a -> f b

class Functor f => Monoidal f where
   unit::f ()
   (*) ::f a -> f b -> f (a,b)

instance Applicative f => Monoidal f where
  unit = pure ()
  a * b = undefined

Я знаю, что мог бы, конечно, добавить явное ограничение Functor f к Monoidal, чтобы не было ошибки, но мой вопрос больше о том, почему разрешение экземпляра работает таким образом.

import Prelude hiding ((*), Applicative (..), Monad (..))

class Functor f => Applicative f where
  pure :: a -> f a
  (<*>) :: f (a -> b) -> f a -> f b

class Functor f => Monoidal f where
   unit::f ()
   (*) ::f a -> f b -> f (a,b)

instance (Applicative f, Functor f) => Monoidal f where
  unit = pure ()
  a * b = (pure (,) <*> a <*> b )

instance (Monoidal f, Functor f) => Applicative f where
  pure x = fmap (\_ -> x) unit
  mu <*> mx = fmap (\(f, x) -> f x) ((mu * mx) :: f (a -> b, a))

person nicolas    schedule 03.11.2017    source источник
comment
Надеюсь, понятно, что такой пример не имеет большого смысла! — Тем не менее, хороший вопрос, я бы тоже предположил, что компилятор это позволит и вычислит суперкласс.   -  person leftaroundabout    schedule 03.11.2017
comment
Основная проблема, которую я вижу, заключается в том, что у вас есть и Functor f => Monoidal f, и Applicative f => Monoidal f. Насколько я понимаю, компилятору нужно видеть только один возможный путь деривации для конкретного класса типов в конкретном типе.   -  person NovaDenizen    schedule 03.11.2017
comment
@leftaroundabout, потому что это изоморфизм туда и обратно, ты это имеешь в виду? вот почему я выложил iso, чтобы напомнить об этом   -  person nicolas    schedule 03.11.2017


Ответы (1)


Похоже на ошибку для меня. Вот минимальный файл, который показывает проблему и не полагается на какие-либо махинации с переименованием Prelude материала или undefined.

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
class A x
class A x => B x
class A x => C x
instance B x => C x

Я рекомендую зарегистрировать ошибку в системе отслеживания ошибок GHC с помощью этого файла (или очень похожего на него); рассуждения, необходимые для обнаружения того, что B x подразумевает A x, должны быть возможны.

person Daniel Wagner    schedule 03.11.2017
comment
Я сообщил об этом как Trac #14417. - person dfeuer; 03.11.2017
comment
И это оказалось известным и официально ожидаемым поведением по состоянию на 8.0. Странный. - person dfeuer; 03.11.2017
comment
И этот комментарий, похоже, приносит деньги, объясняя проблема, которая решается этим поведением. Однако это довольно технично. - person Daniel Wagner; 03.11.2017
comment
это было быстро .. спасибо. это как-то для UndecidableSuperclass. (кстати, UndecidableSuperclass — это прекрасно) - person nicolas; 04.11.2017