Выражение отношений классов типов с функциональными зависимостями в Haskell

Я хочу сказать, что у меня есть 3 связанных класса типов.

У меня есть два файла. Первый:

{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}
module ModA where

class Class a b c | a -> b, b -> c where
    getB :: a -> b
    getC :: b -> c

Второй:

{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}
module B where

import qualified ModA

data A = A {f1::String}

data B = B {f2::String}

data C = C {f3::String}

instance ModA.Class A B C where
    getB a = B "hey"
    getC a = C "ho"

getABForMe = ModA.getB (A "boo")

getACForMe = ModA.getC (B "yo")

Ошибка, которую я получаю:

No instance for (ModA.Class a0 B C)
  arising from a use of `ModA.getC'
Possible fix: add an instance declaration for (ModA.Class a0 B C)
In the expression: ModA.getC (B "yo")
In an equation for `getACForMe': getACForMe = ModA.getC (B "yo")

Что мне не хватает?


person johnny-john    schedule 25.01.2013    source источник


Ответы (2)


Вы можете сделать функциональную зависимость "круговой":

class Class a b c | a->b, b->c, c->a where
    getB :: a -> b
    getC :: b -> c

поэтому любой параметр типа может быть выведен из любого другого. Но я не уверен, действительно ли вы этого хотите; почему бы не иметь только класс типов с одним фондом и одним методом и сделать два его экземпляра (instance Class A B и instance Class B C)?

person leftaroundabout    schedule 25.01.2013
comment
Вот и все! Сработало отлично, спасибо. Что касается «почему», то реальный код, над которым я работаю, сложнее, чем этот небольшой симметричный пример. Считают ли это круговое решение fundep хакерским? - person johnny-john; 25.01.2013

GHC не может знать тип первого параметра класса a в вызове getC. Вызов устанавливает, что b имеет тип B, а затем функциональная зависимость позволяет GHC сделать вывод, что c должно быть C. Но никакой информации о a нет.

person kosmikus    schedule 25.01.2013
comment
Как я могу обойти это тогда? - person johnny-john; 25.01.2013