Либеральное условие покрытия, введенное в коде GHC 7.7, действует в GHC 7.6.

Идея я

я пишуDSL, который компилируется в Haskell.

Пользователи этого языка могут определять собственные неизменяемые структуры данных и связанные с ними функции. Под ассоциированной функцией я подразумеваю функцию, которая принадлежит структуре данных. Например, пользователь может написать (в "вещий» псевдокод):

data Vector a:
  x,y,z :: a
  def method1(self, x):
      return x

(который эквивалентен следующему коду, но показывает также, что связанные функции beheva похожи на классы типов с предположением открытого мира):

data Vector a:
  x,y,z :: a
def Vector.method1(self, x):
  return x

В этом примереmethod1 это функция, связанная сVector тип данных, и может быть использован какv.testid(5) (гдеv это примерVector тип данных) .I '

я перевожу такой код в код на Haskell, но ясталкиваюсь с проблемой, с которой яЯ пытаюсь решить в течение длительного времени.

Проблема я

я пытаюсь переместить код из GHC 7.6GHC 7.7 (предварительная версия 7.8) (Более новые версии могут быть скомпилированыиз источников). Код прекрасно работает под GHC 7.6, но не под GHC 7.7. Я хочу спросить вас, как я могу исправить это, чтобы он работал в новой версии компилятора?

Пример кода

Давайте посмотрим упрощенную версию сгенерированного (моим компилятором) кода на Haskell:

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE FunctionalDependencies #-}

import Data.Tuple.OneTuple

------------------------------
-- data types
------------------------------
data Vector a = Vector {x :: a, y :: a, z :: a} deriving (Show)
-- the Vector_testid is used as wrapper over a function "testid". 
newtype Vector_testid a = Vector_testid a

------------------------------
-- sample function, which is associated to data type Vector
------------------------------
testid (v :: Vector a) x = x

------------------------------
-- problematic function (described later)
------------------------------
testx x = call (method1 x) $ OneTuple "test"

------------------------------
-- type classes
------------------------------
-- type class used to access "method1" associated function
class Method1 cls m func | cls -> m, cls -> func where 
    method1 :: cls -> m func

-- simplified version of type class used to "evaluate" functions based on 
-- their input. For example: passing empty tuple as first argument of `call` 
-- indicates evaluating function with default arguments (in this example 
-- the mechanism of getting default arguments is not available)
class Call a b where
    call :: a -> b

------------------------------
-- type classes instances
------------------------------
instance (out ~ (t1->t1)) => Method1 (Vector a) Vector_testid out where
  method1 = (Vector_testid . testid)

instance (base ~ (OneTuple t1 -> t2)) => Call (Vector_testid base) (OneTuple t1 -> t2) where
    call (Vector_testid val) = val

------------------------------
-- example usage
------------------------------
main = do
    let v = Vector (1::Int) (2::Int) (3::Int)
    -- following lines equals to a pseudocode of ` v.method1 "test" `
    -- OneTuple is used to indicate, that we are passing single element.
    -- In case of more or less elements, ordinary tuples would be used.
    print $ call (method1 v) $ OneTuple "test"
    print $ testx v

Код компилируется и отлично работает с GHC 7.6. Когда я'я пытаюсь скомпилировать его с GHC 7.7, яя получаю следующую ошибку:

debug.hs:61:10:
    Illegal instance declaration for
      ‛Method1 (Vector a) Vector_testid out’
      The liberal coverage condition fails in class ‛Method1’
        for functional dependency: ‛cls -> func’
      Reason: lhs type ‛Vector a’ does not determine rhs type ‛out’
    In the instance declaration for
      ‛Method1 (Vector a) Vector_testid out’

Ошибка вызвана новыми правилами проверки того, что могут делать функциональные зависимости, а именноliberal coverage condition (насколько я знаю, этоcoverage condition расслабился с помощью)-XUndecidableInstances

Некоторые попытки решить проблему

Я пытался преодолеть эту проблему, изменив определениеMethod1 чтобы:

class Method1 cls m func | cls -> m where 
    method1 :: cls -> m func

Что решает проблему с функциональными зависимостями, но затем строка:

testx x = call (method1 x) $ OneTuple "test"

больше не допускается, что приводит к ошибке компиляции (в версиях 7.6 и 7.7):

Could not deduce (Method1 cls m func0)
  arising from the ambiguity check for ‛testx’
from the context (Method1 cls m func,
                  Call (m func) (OneTuple [Char] -> s))
  bound by the inferred type for ‛testx’:
             (Method1 cls m func, Call (m func) (OneTuple [Char] -> s)) =>
             cls -> s
  at debug.hs:50:1-44
The type variable ‛func0’ is ambiguous
When checking that ‛testx’
  has the inferred type ‛forall cls (m :: * -> *) func s.
                         (Method1 cls m func, Call (m func) (OneTuple [Char] -> s)) =>
                         cls -> s’
Probable cause: the inferred type is ambiguous

РЕДАКТИРОВАТЬ:

Также невозможно решить эту проблему, используя семейства типов (насколько я знаю). Если мы заменимMethod1 введите class и instance с помощью следующего кода (или simmilar):

class Method1 cls m | cls -> m where 
    type Func cls
    method1 :: cls -> m (Func cls)

instance Method1 (Vector a) Vector_testid where
    type Func (Vector a) = (t1->t1)
    method1 = (Vector_testid . testid)

Мы получили бы очевидную ошибкуNot in scope: type variable ‛t1’потому что семейства типов не позволяют использовать типы, которых нет в LHS выражения типа.

Последний вопрос

Как я могу заставить эту идею работать в GHC 7.7? Я знаю новоеliberal coverage condition позволяет разработчикам GHC добиться некоторого прогресса в проверке типов, но это должно как-то выполнимо перенести идею, работающую в GHC 7.6, на версию без компилятора.

(не заставляя пользователя моего DSL вводить какие-либо дополнительные типы - пока что все, например, экземпляры классов типов,с помощью Template Haskell)

Ответы на вопрос(1)

Ваш ответ на вопрос