Здравствуйте, deniok, Вы писали:
D>написание instance Num [a] остается читателю в качестве упражнения
А почему Hugs выдает ошибку? В какой момент должна возникать ошибка, если нет нужного инстанса — при компиляции определения функции или при компиляции ее вызова?
Здравствуйте, nikov, Вы писали:
N>А почему Hugs выдает ошибку? В какой момент должна возникать ошибка, если нет нужного инстанса — при компиляции определения функции или при компиляции ее вызова?
N>И почему такой код вызывает ошибку?
N>
N>let f x = let g y = [x,y] in (g 1, g "")
N>
Видите ли, тут всё дело в выводе типов. Как Вы догадались, в одном списке не могут присутствовать значения разных типов. Однако, [] — полиморфный конструктор списка. Так получается, что в Вашем примере именно этот конструктор "подстраивается" под второй вызов с числовым аргументом. А пустая строка — конкретно список символов. В этом и разница.
Ошибка возникает в том месте, где type-checker не может вывести тип выражения.
Здравствуйте, nikov, Вы писали:
N>И почему такой код вызывает ошибку?
N>
N>let f x = let g y = [x,y] in (g 1, g "")
N>
Здесь нет контекста, поскольку нет полиморфизма. Поэтому ищется instance Num [Char] (и не находится). А Num [a] — вполне валидный контекст (здесь есть переменная типа), хотя, конечно, каждый понимает, что "разумный" instance для него не написать. Если включить -XOverloadedStrings (с полиморфными строками), то опять появится полиморфизм и типизация опять будет допустима, в контексте (Num [a], IsString a) => ...
Здравствуйте, Code Digger, Вы писали:
CD>И как такой код будет выполняться??? Для каких аргументов f он имеет корректную типизацию?
Именно эту функцию можно вызвать только с x=_|_ . Если ограничить переменную типов 'a' каким-то контекстом, можно будет передавать отличные от задницы полиморфные аргументы
{-# LANGUAGE RankNTypes #-}class Foo a where
quux :: a
bzzt :: a
instance Foo String where
quux = "quux"
bzzt = "bzzt"instance Foo Int where
quux = 42
bzzt = 1
f :: (forall a . (Foo a) => a) -> ([Int], [String])
f x = let g y = [x,y] in (g 1, g "")
main =
do print (f quux)
print (f bzzt)