Вариадики на хаскеле. (o_O)
От: Кодт Россия  
Дата: 25.05.17 17:48
Оценка:
Как сделать функцию настолько полиморфной, чтобы она принимала произвольное количество произвольных аргументов?
Понятно, что можно взять обобщённый список и подать его как единственный аргумент
{-# 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"]]


Но Дэвид Блейн покажет нам настоящую, уличную магию и сделает карринг!
https://habrahabr.ru/post/324190/

Однако, IdeOne отказался компилировать первый же пример: http://ideone.com/DLTa60

Что скажете? Пребываю в недоумении...
Перекуём баги на фичи!
Re: Вариадики на хаскеле. (o_O)
От: deniok Россия  
Дата: 26.05.17 05:58
Оценка: 72 (1)
Здравствуйте, Кодт, Вы писали:

К>Что скажете? Пребываю в недоумении...


Надо добавить тип для magic
magic :: VarArgs a => a
Re[2]: Вариадики на хаскеле. (o_O)
От: Кодт Россия  
Дата: 26.05.17 09:45
Оценка:
Здравствуйте, 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) -- нихьт компилирен
Перекуём баги на фичи!
Re[3]: Вариадики на хаскеле. (o_O)
От: deniok Россия  
Дата: 26.05.17 10:17
Оценка:
Здравствуйте, Кодт, Вы писали:

Надо добавить тип для shmagic и figagic
shmagic, figagic  :: VarArgs a => t -> a

Вывод типов в системах высших рангов — неразрешимая задача, а мы там оказались, включив расширение RankNTypes. Поэтому по умолчанию стоит аннотировать типами все, что используется. Имеющийся алгоритм вывода кое-где позволяет опускать явное приписывание, но, если с этим не работать все время, то все равно все случаи и подслучаи вылетают из головы.
Re[4]: Вариадики на хаскеле. (o_O)
От: Кодт Россия  
Дата: 26.05.17 12:45
Оценка:
Здравствуйте, 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

Безо всяких высших рангов :\
Перекуём баги на фичи!
Re[5]: Вариадики на хаскеле. (o_O)
От: deniok Россия  
Дата: 26.05.17 13:01
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Безо всяких высших рангов :\


А здесь бесточечный стиль, поэтому тоже требуется аннотация. Если добавить аргумент слева и справа — должен вывести.
Re[6]: Вариадики на хаскеле. (o_O)
От: Кодт Россия  
Дата: 26.05.17 16:57
Оценка:
Здравствуйте, 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

Чем 1 отличается от show?
Перекуём баги на фичи!
Re[5]: Вариадики на хаскеле. (o_O)
От: deniok Россия  
Дата: 26.05.17 17:41
Оценка: 70 (1)
Здравствуйте, Кодт, Вы писали:

К>
К>pst :: Show t => t -> IO()  -- без аннотации это сломает компиляцию функции ps !!!
К>pst = putStrLn . show

К>ps t = (putStrLn . show) t  -- а здесь аннотация не нужна
К>

К>Безо всяких высших рангов :\

Вспомнил откуда ноги растут! Тут надо добавить прагму NoMonomorphismRestriction и все скомпилируется без аннотации. (Эту прагму, вообще, надо повсюду добавлять, Monomorphism Restriction не нужен.)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.