2015-04-13 3 views
8

Я не мог найти ответ на свой вопрос среди нескольких неоднозначных переменных переменных ошибок.Haskell - Неоднозначная переменная типа

В основном я хочу взять информацию о типе на уровень значения. Последняя строка в этом примере завершается с ошибкой.

{-# LANGUAGE MultiParamTypeClasses #-} 
{-# LANGUAGE FunctionalDependencies #-} 
{-# LANGUAGE FlexibleInstances #-} 
{-# LANGUAGE UndecidableInstances #-} 
{-# LANGUAGE TypeOperators #-} 

module Test where 

data Typ = TInteger | TString deriving Show 

data Empty = Empty 
data a ## b = Cons a b 

class Typical a b | a -> b where 
    typical :: a -> b 

instance Typical Empty [Typ] where 
    typical _ = [] 

instance Typical Integer Typ where 
    typical _ = TInteger 

instance Typical String Typ where 
    typical _ = TString 

instance (Typical a Typ, Typical b [Typ]) => Typical (a ## b) [Typ] where 
    typical _ = typical (undefined :: a) : typical (undefined :: b) 

Вот первое сообщение об ошибке:

Test.hs:27:17: 
Could not deduce (Typical a0 Typ) arising from a use of `typical' 
from the context (Typical a Typ, Typical b [Typ]) 
    bound by the instance declaration at Test.hs:26:10-67 
The type variable `a0' is ambiguous 
Possible fix: add a type signature that fixes these type variable(s) 
Note: there are several potential instances: 
    instance Typical String Typ -- Defined at Test.hs:23:10 
    instance Typical Integer Typ -- Defined at Test.hs:20:10 
Possible fix: add an instance declaration for (Typical a0 Typ) 
In the first argument of `(:)', namely `typical (undefined :: a)' 
In the expression: 
    typical (undefined :: a) : typical (undefined :: b) 
In an equation for `typical': 
    typical _ = typical (undefined :: a) : typical (undefined :: b) 

Я просто не понимаю.

Что такое a0? Может быть, a из моей последней строки не отождествляется с тем, что со второй последней строки?

Где я должен поставить подпись типа и почему?

Пожалуйста, просветите меня!

+0

Добавление функциональной зависимости утверждает, что один тип [уникально определен другим] (https://wiki.haskell.org/Functional_dependencies). Я считаю, что вам нужно либо удалить один из экземпляров «Типичный тип», либо создать конкретные экземпляры для каждого возможного варианта вашего комбинированного экземпляра. – Mokosha

+2

@Mokosha: Функциональная зависимость - это 'a -> b', а не' b -> a', поэтому я не думаю, что экземпляры должны быть удалены. Я не думаю, что получил вторую часть вашего последнего предложения. –

ответ

5

Хорошо, у меня есть решение, но я не знаю, является ли это самым чистым обходным решением.

Добавление {-# LANGUAGE ScopedTypeVariables #-} делает код скомпилированным. Это позволяет идентифицировать a0 с a из сообщения об ошибке (соответствующего a s из двух последних строк кода).

Прокомментируйте!

+1

'ScopedTypeVariables' - это правильный способ получить то, что вы хотите. В противном случае переменные в аннотациях локального типа неявно определяются количественно. Независимо, если вам никогда не нужно фактическое значение первого аргумента «типичный», вероятно, лучше использовать прокси: https://hackage.haskell.org/package/base-4.8.0.0/docs/Data-Proxy. html # t: Прокси – kosmikus

+0

@kosmikus: Спасибо. После выполнения этой ссылки у меня сложилось впечатление, что 'Data.Reflection' делает то, что я пытался построить здесь. –

Смежные вопросы