Haskell. Подача программы с параметрами (в чистом виде) - PullRequest
1 голос
/ 09 июня 2011

Меня интересуют возможные способы ввода параметров в мою программу.Это физическое моделирование, и мне нужно ввести температуру, количество шагов и т. Д.

Однако мне нужны эти параметры, чтобы они были чистыми, поэтому я не могу использовать IO.Следовательно, по крайней мере, часть моей программы должна быть перекомпилирована каждый раз.Каков наилучший метод для достижения этой цели?

Насколько я помню, xmonad использует ту же технику.

UPD Кажется, Dyre делает то, что мне нужно.http://hackage.haskell.org/package/dyre Попробуем.

UPD2 Дир делает немного другое.

Ответы [ 4 ]

9 голосов
/ 09 июня 2011

Из комментария к вопросу:

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

Здесь есть некоторые неявные заблуждения, которые необходимо изучить.

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

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

Кроме того, из самого вопроса:

Однако мне нужно, чтобы эти параметры были чистыми, поэтому я не могу использовать IO.Следовательно, по крайней мере, часть моей программы приходится перекомпилировать каждый раз.

Чистые параметры - нет.Это постоянные значения.Вы можете определить их в другом месте исходного кода, но после компиляции они будут фиксированными и неизменными.Если программе требуется доступ к параметрам, которые do изменяются после компиляции, то имеет для использования ввода / вывода.Это практически определение ввода / вывода!

Имейте в виду, что даже если вам нужно получить значения в вычислении IO, вся действительная логика может быть выполнена в чистой функциивот так:

main :: IO ()
main = do x <- getParameter
          let r = lotsOfCalculations x
          print r

Функция lotsOfCalculations, как и все, что она использует, будет чистой функцией.Единственное использование IO - получение параметров.

Кроме того, для краткости обратите внимание, что приведенный выше код также можно записать как main = getParameter >>= print . lotsOfCalculations.

2 голосов
/ 09 июня 2011

Используйте монаду читателя, например Reader r из Control.Monad.Reader. Затем запустите вычисление, используя runReader.

Вы передаете параметры моделирования в runReader, тогда компоненты вашего моделирования могут получить к ним доступ, используя ask и asks.

(Примечание: для этого необходимо объединить все параметры в один тип данных.)

1 голос
/ 09 июня 2011

Попробуйте использовать замыкание,

doCalculation params input = inner input where
    inner = ... (references params variable)
    inner2 = ... (references params variable)

В общем, в Хаскеле, когда вы пытаетесь нарушить чистоту, случаются плохие вещи.Например, завершение вызова генератора случайных чисел в unsafePerformIO означает, что вы не получите случайные числа, так как он начнет повторное использование вычисления (неожиданным образом).

Кроме того, есть типы записей, так что вы можетесоздать что-то вроде

data Params = Params { name :: String, speed :: Double }
1 голос
/ 09 июня 2011

Если вы не запускаете эту программу внутри интерпретатора, вам придется погрузиться в IO в какой-то момент.Скорее всего, через основную функцию, которая является нечистой.

В любом случае, просто спроектируйте свои функции как чистые.В своих нечистых функциях вы можете использовать монаду Maybe для очистки значений, а затем передавать (или не передавать в случае Ничего) их в свои чистые функции.

Имейте в виду, чтобы получить любой видВыходные данные из программы должны будут проходить через функцию ввода-вывода, явно (например, основная функция) или неявно (интерпретатор).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...