2015-12-20 2 views
2

Я пишу программу в Scala и стараюсь оставаться функционально чистым, насколько это возможно. Проблема, с которой я сталкиваюсь, не специфична для Scala; это больше связано с попыткой кода функционально. Логика функции, которую я должен кода идет что-то вроде:Как отделить проблемы функционально

  1. Потратьте некоторое значение типа А
  2. Используйте это значение для формирования информации из журнала
  3. Войти эту информацию посредством вызова функции во внешней библиотеке и оценивать статус возврата для действия регистрации (т. е. был ли он успешным журналом или произошел сбой регистрации)
  4. Независимо от того, был ли журнал успешным или неудачным, я должен вернуть значение ввода.

Причина для возвращения значения входного в качестве выходного значения, что эта функция будет состоять с другой функцией, которая требует значения типа А.

Учитывая выше, функцию Я пытаюсь кода действительно имеет тип A => A, т. е. он принимает значение типа A и возвращает значение типа A, но между ними выполняется некоторая регистрация. Тот факт, что я возвращаю то же значение обратно, которое я ввел, заставляет эту функцию сводиться к функции идентификации!

Это похоже на запах кода для меня, и мне интересно, что я должен сделать, чтобы сделать эту функцию более чистой. Как я могу выделить здесь проблемы? Также тот факт, что функция журнала уходит и регистрирует информацию, означает, что я действительно должен обернуть этот вызов в монаду IO и вызвать функцию unsafePerformIO. Любые идеи приветствуются.

+0

Если единственной целью является регистрация, это должно быть 'A -> IO()' not 'A -> A'. –

+1

функция ведения журнала не обязательно имеет какое-либо отношение к IO, но вы можете использовать Writer Monad, возможно, оставив вам функцию типа A => Writer A', которая затем вы можете выполнить операции ввода-вывода на –

+0

Я принял совет @BartekBanachewicz и изменил подпись функции на «A -> IO [Unit]». Затем я составляю другие функции с этим действием IO монадически в выражении for (эквивалент 'do' в Haskell). –

ответ

0

То, что вы описываете, больше похоже на отладку, чем на журнал. Например, Haskell's Debug.Trace.trace делает именно это, и в его документации говорится: «Они могут быть полезны для расследования ошибок или проблем с производительностью. Они не должны использоваться в производственном коде».

Если вы выполняете ведение журнала, функция ведения журнала должна только регистрироваться и не иметь дополнительного возвращаемого значения. Как уже упоминалось выше @Bartek, его тип будет A -> IO(), то есть не возвращает никакой информации () и имеет побочные эффекты (IO). Например, Haskell's hslogger library предоставляет такие функции.

Смежные вопросы