К>pst :: Show t => t -> IO() -- без аннотации это сломает компиляцию функции ps !!!
К>pst = putStrLn . show
К>ps t = (putStrLn . show) t -- а здесь аннотация не нужна
К>
К>Безо всяких высших рангов :\
Вспомнил откуда ноги растут! Тут надо добавить прагму NoMonomorphismRestriction и все скомпилируется без аннотации. (Эту прагму, вообще, надо повсюду добавлять, Monomorphism Restriction не нужен.)
Как сделать функцию настолько полиморфной, чтобы она принимала произвольное количество произвольных аргументов?
Понятно, что можно взять обобщённый список и подать его как единственный аргумент
{-# LANGUAGE ExistentialQuantification, GADTs #-}data S = forall a . Show a => S a
join :: [S] -> String
join = (foldr (\x y -> x ++ ";" ++ y) "") . (map (\(S x) -> show x))
main = putStrLn $ join [S 1, S "2", S (), S ["hello","world"]]
Здравствуйте, deniok, Вы писали:
D>Надо добавить тип для magic
То есть, без этой аннотации компилятор считает, что prc "" имеет тип String, потому что... почему?
Потому что между типами String и String->xz (оба из которых подходят под класс VarArgs) он сперва выберет то, где нет переменных типа, — а уже потом налетит на оператор пробел в выражении (f 1)?
И это касается только констант верхнего уровня?
Ведь стоит написать
shmagic _ = prc ""
figagic = const $ prc ""-- казалось бы, то же, что и выше, но фиг!
main = do
useMagic (prc "")
useMagic (shmagic 0)
useMagic (figagic 0) -- нихьт компилирен
Вывод типов в системах высших рангов — неразрешимая задача, а мы там оказались, включив расширение RankNTypes. Поэтому по умолчанию стоит аннотировать типами все, что используется. Имеющийся алгоритм вывода кое-где позволяет опускать явное приписывание, но, если с этим не работать все время, то все равно все случаи и подслучаи вылетают из головы.
Здравствуйте, deniok, Вы писали:
D>Надо добавить тип для shmagic и figagic
IdeOne считает, что shmagic (равно как и копипасты выражений из magic и figagic по месту использования) прекрасно обходится без аннотации.
В отличие от глобальных значений magic и figagic.
Вот это и смущает.
D>Вывод типов в системах высших рангов — неразрешимая задача, а мы там оказались, включив расширение RankNTypes. Поэтому по умолчанию стоит аннотировать типами все, что используется. Имеющийся алгоритм вывода кое-где позволяет опускать явное приписывание, но, если с этим не работать все время, то все равно все случаи и подслучаи вылетают из головы.
На самом деле, такие ситуации можно поймать на ровном месте в гораздо более простых условиях. http://ideone.com/jy5ibg
one _ = 1
two _ = 2
tri _ = 3 :: Int
fur _ = 4.0
one0 = one 0
two0 = two 0
tri0 = tri 0
fur0 = fur 0
pst :: Show t => t -> IO() -- без аннотации это сломает компиляцию функции ps !!!
pst = putStrLn . show
ps t = (putStrLn . show) t -- а здесь аннотация не нужна
main = do
ps $ one0 + tri0 -- чтобы компилировалось, надо константы заменить на выражения one 0, two 0
ps $ two0 + fur0
ps $ one0 + two0
Здравствуйте, deniok, Вы писали:
К>>Безо всяких высших рангов :\
D>А здесь бесточечный стиль, поэтому тоже требуется аннотация. Если добавить аргумент слева и справа — должен вывести.
Хотелось бы понять такую простую вещь.
Вот у нас есть константы
one = 1 -- неявно Num t => t, тип будет выведен позднее, по месту использования
two = 2
one' :: Num t => t -- с такой аннотацией получили полиморфную константу, куда хочешь, туда и подставляешь
one' = 1
two' :: Num t => t
two' = 2
sss = show -- неявно Show t => t -> String, аннотация нужна прямо здесь и сейчас (даже если не используется)
sss' :: Show t => t -> String
sss' = show