2017-01-04 8 views
0

У меня есть тип:Не удалось вывести (класс типов а0), вытекающее из использования «переменной»

type DifferentiableFunction n a = (Function n a, List n (Function n a), String) 

В другом месте я определяю:

data Something where 
    Operator :: Something -> (forall a . Floating a => DifferentiableFunction n a) -> Something 

Теперь я пытаюсь сопоставления с образцом:

case something of 
    (Operator s f) -> let (_, _, l) = f in l 

Я получаю Could not deduce (Floating a0) arising from a use of ‘f’. Я не понимаю, почему это происходит.

+0

Почему вы используете этот универсальный тип? Чего вы пытаетесь достичь? – chi

+0

Я пытаюсь ограничить тип функций теми, кто работает с типами «Плавающие». Моя ранняя декларация была «data Something a» без универсального типа, но я столкнулся с другими проблемами. Это связано с переносом 'Something a' в экзистенциальную оболочку (у нее есть другие параметры, кроме' a') и с использованием пакета 'ad' (дифференцируемый тип функции немного вводит в заблуждение, мне просто нужна помеченная функция). Мой код в значительной степени работает сейчас, кроме этой функции, которая пытается извлечь ярлык. Я могу позже задать другой вопрос о восстановлении параметра 'a'. – denormal

+0

@chi Короче говоря: пакет 'ad' не работает с конкретными типами, такими как' Double', ему нужны эти ограничения типа (фактически универсальный квантификатор), чтобы иметь возможность использовать свои собственные типы, которые их создают. – denormal

ответ

2

Проблема заключается в том, что let (_, _. l) = f in l не определяет, какой тип использовать для f: это может быть DifferentiableFunction n Double или DifferentiableFunction n Float или что-то совсем другое. Потому что вы используете только часть, которая не зависит от a (l - это всего лишь String, независимо от того, что a есть), компилятор не может решить, какой тип f должен иметь (a является двусмысленным, т.е. компилятор не знает, что выберите для a).

Решение поэтому дать явную сигнатуру типа для F:

case something of 
    (Operator s f) -> let (_, _, l) = (f :: DifferentiableFunction n Double) in l 

Или же, приподнять String из FORALL:

type DifferentiableFunction n a = (Function n a, List n (Function n a)) 
data Something where 
    Operator :: Something -> (forall a . Floating a => DifferentiableFunction n a) -> String -> Something -- String is not inside the `forall a.` 

Теперь вы можете получить String без необходимости выбрать конкретный a, потому что он действительно не зависит от a.

+0

Спасибо. Если я выбираю Double, а затем использую то же самое «что-то», где-то, где требуется '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' \\\\\\\\\\\\\? – denormal

+0

@ denormal no, что не вызовет проблем, поскольку привязка 'f' является полиморфной из-за forall, поэтому ее можно использовать в разных типах в разных местах. – bennofs