Oberon space
General Category => Общий раздел => Тема начата: Peter Almazov от Октябрь 11, 2011, 08:22:30 am
-
Периодически у меня возникают дурацкие вопросы, с которыми я не решился бы лезть на специализированный форум. Надеюсь, видные хаскелеводы здесь помогут чайнику.
Взял исходный текст задачи Эйнштейна здесь http://habrahabr.ru/blogs/Haskell/122123/ и скормил его WinGHCi 1.0.6. Запускаю Run "main", среда задумывается, потом выдает ответ. Ресурсы: (1.77 secs, 140068460 bytes)
Если запускать еще, то мгновенно выдается ответ, ресурсы (0.00 secs, 0 bytes). Что, вообще, происходит второй и все последующие запуски? Почему так быстро и без затрат памяти?
-
Кстати, вот текст. А то его получение из страницы на хабре - нетривиальная задача.
-
Взял исходный текст задачи Эйнштейна здесь http://habrahabr.ru/blogs/Haskell/122123/ и скормил его WinGHCi 1.0.6. Запускаю Run "main", среда задумывается, потом выдает ответ. Ресурсы: (1.77 secs, 140068460 bytes)
Если запускать еще, то мгновенно выдается ответ, ресурсы (0.00 secs, 0 bytes). Что, вообще, происходит второй и все последующие запуски? Почему так быстро и без затрат памяти?
Просто интерпретатор прокешировал результаты вычисления программы и печатает уже ранее вычисленное значение.
-
Ах, ну да, побочных эффектов нет, функции можно смело кешировать.
Непривычно.
-
WinGHCi, кстати, это просто ГУИ-оболочка для GHCi.
Удобная консолька, но запоминает слишком большую историю команд, и не понятно как очистить ))
ЗЫ. GHCi, оказывается, тоже хранит историю ввода ))
-
А про WinHugs что-нибудь можете сказать? У него есть более-менее дружественный хелп, но текст задачи он не жрет.
Чем народ-то пользуется?
-
я лично обычно пользуюсь WinHUGS, но если он оказывается несовместим с той или иной программой на хаскелле (то ли расширение языка не поддерживает, то ли библиотеки не так реализованы или вообще отсутствуют), то компилирую в GHC. Реже GHCi или WinGHCi (когда вспоминаю про него).
У WinHUGS есть интересные фишки -- браузер классов, конструкторов и тд, в частности просмотрщик иерархий классов. Правда я этим добром почти не пользуюсь...
-
А про WinHugs что-нибудь можете сказать? У него есть более-менее дружественный хелп, но текст задачи он не жрет.
Что бы Winhugs принял эту задачу, надо в начале файла после секции импорта вставить строку
default(Int)
то есть начинаться этот файл должен так:
import Data.List (lookup,nub)
import Data.Maybe (fromMaybe,catMaybes)
default(Int)
Функция objectAt принимает на вход целое число типа Int, а по умолчанию целочисленные константы в выражениях принимают значение Integer, если у транслятора нет подсказок, что достаточно типа Int.
В данном случае в функции
-- один объект всегда следует за другим
before obj obj' = r_any [
objectAt n obj <&> objectAt (n + 1) obj' | n <- [1..size - 1] ]
такой информации нет, и HUGS решает, что n и 1 в выражении objectAt (n + 1) obj' | n <- [1..size - 1] имеют тип Integer.
Этому выводу способствует неуказанный тип константы size, который принимается равным Integer.
GHC же более умный, учитывает тип функции objectAt и правильно обрабатывает такой случай.
Хотя по идее он тоже должен был ругнуться на это место.
Ещё WinHUGS решает эту задачу заметно медленнее, чем GHCi.
-
Спасибо за подробное объяснение!
-
Кстати, раз вас заинтересовала головоломка Энштейна, то может будет интересна и эта:
Мартин Эрвиг. Побег от Зурга: упражнение в логическом программировании
http://fprog.ru/lib/martin-erwig-escape-from-zurg/
Тут задачка попроще, и с более подробными объяснениями.
Перевод, правда, не ахти (я её переводил 4 года назад, при том что я сам не очень знаю этот ихний инглиш, да и хаскелл я тогда только начал изучать)...
-
Спасибо.
Несмотря на то, что вторая задача проще, с первого взгляда я мало что понял в решении.
Если найду время, попробую решить эти задачи на императивном языке (C# в данном случае) и сопоставить решения с Haskell'ными.
-
Мартин Эрвиг. Побег от Зурга: упражнение в логическом программировании
http://fprog.ru/lib/martin-erwig-escape-from-zurg/
Просьба пояснить этот момент (первый вариант SearchProblem):
space s = step ++ expand step
where step = [ ([m],t) | (m,t) <- trans s ]
expand ss = [ (ms++ns,t) | (ms,s) <- ss,
(ns,t) <- space s ]
"space s" определяется через "space s". Бесконечная рекурсия, насколько я понимаю.
В конце статьи во втором варианте SearchProblem на этом месте стоит trans s.
Есть ошибка, или это я торможу?
P.S. Видимо, второе, т.к. там речь идет о бесконечных конструкциях.
Ну, может во втором варианте ошибка?
-
Просьба пояснить этот момент (первый вариант SearchProblem):
space s = step ++ expand step
where step = [ ([m],t) | (m,t) <- trans s ]
expand ss = [ (ms++ns,t) | (ms,s) <- ss,
(ns,t) <- space s ]
"space s" определяется через "space s". Бесконечная рекурсия, насколько я понимаю.
В конце статьи во втором варианте SearchProblem на этом месте стоит trans s.
Есть ошибка, или это я торможу?
P.S. Видимо, второе, т.к. там речь идет о бесконечных конструкциях.
Ну, может во втором варианте ошибка?
Оба варианта правильные, вычисляют верно одно и тоже решение.
Тут проблема в так называемом "name hiding" -- в выражении
[ (ms++ns,t) | (ms,s) <- ss,
(ns,t) <- space s ]
s -- уже не та s, что является параметром функции s. Она выбирается из переменной step в выражении
expand step
where step = [ ([m], t) | (m, t) <- trans s ]
Более наглядно, наверное, было бы записать этот код так:
space s = step ++ expand step
where step = [ ( [m], t) | (m, t) <- trans s ]
expand ss = [ (ms ++ ns, t) | (ms, s') <- ss
, (ns, t) <- space s' ]
-
Я вот сейчас книгу по языку "Clean" читаю.
Clean -- хаскеллоподобный язык. Почему же не сам Хаскелл?
По сравнению с хаскеллом мне клин показался каким-то заумным -- одни только списки чего стоят: ленвые с начала, ленивые с конца, энергичные с начала... тьфу!
Уникальные типы, насколько я понял, не имеют преимуществ перед монадой IO, хотя и являются по мнению некоторых людей интересной концепцией.
Кстати, последняя реализация компилятора Clean имет возможность и хаскельные программы компилировать, но что-то я так и забыл посмотреть, как там оно... ;D
Я в Clean еще не врубился, но желание пока не пропало. Может, впереди и ждет разочарование. С другой стороны идея Хаскеля использовать монады для ввода-вывода мне вполне определенно не нравится.
Вся эта функциональщина продвигается ни шатко, ни валко, в свободное время.
-
http://blog.ezyang.com/2011/11/how-to-read-haskell/
А ведь врет мужик:
Arguments. f a b c translates into f(a, b, c). Haskell code omits parentheses and commas.
f может иметь не 3, а 1 или 2 параметра и возвращать функцию. Тогда возможно
f(a)(b, c)
f(a,b)(c)
-
http://blog.ezyang.com/2011/11/how-to-read-haskell/
А ведь врет мужик:
Arguments. f a b c translates into f(a, b, c). Haskell code omits parentheses and commas.
f может иметь не 3, а 1 или 2 параметра и возвращать функцию. Тогда возможно
f(a)(b, c)
f(a,b)(c)
В питоне нет такого понятия как каррирование, поэтому, видимо, автор статьи и не рассматривал такие варианты.
Хотя должен бы указать что-то типа, что иногда функция f может выглядеть как что-то типа
def f a : lambda (b, c): ...
или как там у них в питоне лямбды выглядят...