LINUX.ORG.RU

Что делают хаскеллисты если нужно внезапно выполнить I/O?

 


1

4

Я как императивщик до мозга костей часто попадаю в следующую ситуацию. Есть какое-то сложное вычисление, которое можно представить как чистую функцию. Но так как оно сложно, то разбиваем его на подфункции. Например, эквивалентый полупсевдокод на импертивном языке и хаскелле:

def func(args):
    a = subfunc1(args)
    b = subfunc2(a)
    return subfunc3(b)
func args = subfunc3 b where
     b = subfunc2(a)
     a = subfunc1(args)

Функции работают одинаково, плюс относительно хаскелловской функции я знаю что она не зависит от глобального состояния и прочий хаскелловский блёрб.

Но тут ВНЕЗАПНО я понял, что хотел бы логгировать все случаи, когда subfunc1 выдал какой-то определенный результат. В случае с императивным кодом все просто

def func(args):
    a = subfunc(args)
    if some_condition(a):
        logger.warning('Some shit happened')
    ....

В хаскелле для такого надо фактически все с нуля переписывать через какую-то монаду.

Вопрос, как правильно писать на хаскеле чтоб в такой ситуации отделываться минимальными изменениями кода?

★★★★★

import Debug.Trace

и использовать функцию trace. Может она там внутри и unsafeIO, но вы этого не заметите, и вас это волновать не будет. Логгирует, печатает и тп просто замечательно и когда надо.

b = subfunc2 $ trace (if some_condition a then (show a) else "") a

anonymous
()
Ответ на: комментарий от anonymous

Рассмешил, содомит. Даже больше, чем местные воннаби-хаскел-профи.

anonymous
()
Ответ на: комментарий от qnikst

уровень в слой будь то Par/ST/IO не в счет

Ещё Identity неплохо убирается. Т.е. код ТС можно записать монадично как

-- func :: MonadIO m => Int -> m Int
func args = do
  a <- subfunc1 args
  when (someCondition a) $
    warning logger "Some shit happened"
  b <- subfunc2 a
  subfunc3 b

так что func args :: Identity Int будет компилироваться обычно (то есть можно ожидать тех же инструкций, что от (subfunc3 (subfunc2 (subfunc1 args))) с немонадными функциями), с выкидыванием условия when, а func args :: IO Int — как обычный IO, с выполнением условия when.

quasimoto ★★★★
()

Если это только для дебага - Debug.trace. В остальных случаях - монада. Переписать с нуля - преувелечение, так что всё норм. Тем более, что внезапных факапов с логгингом не будет.

anonymous
()

ВНЕЗАПНО? Это как вообще? Используя какие ресурсы, надо ВНЕЗАПНО осуществить ввод/вывод?

В коде, где архитектурно не предполагается никакого ввода-вывода, не будет возможности этот ввод-вывод внезапно сделать. В таком коде доступны разве что какие-нибудь stdin/stdout. Но по поводу вреда глобального состояния и синглтонов уже и без нас много слов сказано.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.