2010-07-25 5 views
1
class Visible a where 
toString :: a -> String 
size :: a -> Int 

intToString :: (Integral t) => t -> String 
intToString 0 = "0" 
intToString 1 = "1" 
intToString 2 = "2" 
intToString 3 = "3" 
intToString 4 = "4" 
intToString 5 = "5" 
intToString 6 = "6" 
intToString 7 = "7" 
intToString 8 = "8" 
intToString 9 = "9" 
intToString n 
| ((div n 10) == 0) = (intToString (mod n 10)) 
| otherwise   = (intToString (div n 10)) ++ (intToString (mod n 10)) 

ТеперьInt против Integer в экземпляре класса

instance Visible Int where 
toString = intToString 
size n = length (toString n) 

дает мне ошибку о переменной неоднозначного типа в командной строке, если я типа что-то вроде (ToString 55)

но

instance Visible Integer where 
toString = intToString 
size n = length (toString n) 

нет.

Что дает?

+3

FYI, вот альтернативное определение вашей intToString: 'intToString = show' – luqui

ответ

0

Я нашел по адресу this link a возможное описание. Я думаю, что интерпретация по умолчанию для литерала по умолчанию - это Integer в ghci. Но если это не сработает, ghci начинает путаться, о какой интерпретации литерала он должен сделать (Int, Double, Float, ...). Впоследствии он дает ошибку о двусмысленности. Команда (toString (55:Int)) не дает ошибки, потому что GHCi знает, что он должен интерпретировать 55 как Int.

Вы применяете этот метод не к значению определенного типа, но значение другого перегруженного типа, а именно ваши буквальный 5. Это означает, что Haskell должен выяснить, какие конкретный тип выбрать для «а» в этом случае. Классы классов Haskell открыты, и обычно это не случайно. выберите один, если несколько может матч. В этом случае есть экземпляр для Integer (в вашем первом примере) или Int (во втором), но там также может быть другим для Float или Double. Какой из них будет правильным? Ну, как я уже сказал, обычно Haskell здесь консервативен и просто жалуется, поэтому ошибка «Неопределенная переменная типа» вы получаете во втором случае. Однако в Haskell есть механизм, чтобы дать эвристику, и вот что такое «дефолт». При нормальных обстоятельствах Haskell, для числовых типов, выбирает «Целое число» в случаях двусмысленности, , и если это не сработает, он попытается «Двойной». Он не пытается «Int» . Это объясняет, почему работает ваш первый пример (случайно). Если вы спросите GHCi о типе, то по умолчанию не применяется, но вы, , можете наблюдать, как это происходит во многих местах. Например,

15

Здесь есть две вещи. Помните, что числовые литералы в Haskell являются полиморфными. То есть:

x = 55 

действительно означает

x :: Num a => a 
x = fromIntegral 55 

Это верно для всех чисел в любом месте вы пишете их. Это может быть неудобно работать, поэтому GHCi реализует тип по умолчанию: он предполагает, что голые числа: Integers или Doubles, если тип неоднозначен.

Когда вы пишете toString 55 по приглашению GHCi, GHCi вводит тип (Visible a, Num a) => a для номера 55.Если у вас только Visible Int в области, тип по умолчанию Integer не работает, потому что он не выполняет ограничение класса (нет Visible Integer), поэтому GHCi жалуется на переменную неоднозначного типа, потому что не знает, какой тип для создания экземпляра для выражения. Если у вас есть Visible Integer в области, тип по умолчанию Integer работает просто отлично.

Если вы хотите использовать тип, кроме Integer, вы можете использовать явный тип как в toString (55 :: Int)

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