我对在程序中提供参数的可能方法感兴趣。这是一个物理模拟,我需要输入温度,步数等。
但是我需要这些参数是纯粹的,所以我不能以任何方式使用IO。因此,每次我的程序的至少一部分必须重新编译。实现这一目标的最佳方法是什么?
据我所知,xmonad使用相同的技术。
UPD 似乎Dyre做我需要的。 http://hackage.haskell.org/package/dyre试试吧。
UPD2 Dyre有点不同。
答案 0 :(得分:9)
来自对该问题的评论:
我不想将它们作为参数传递给它,因为它很笨重 - 在这种情况下,所有函数都需要一个额外的参数。而且我不确定这只有几个全局函数(代表参数)的效率。
这里隐含的一些误解需要加以研究。
首先,众所周知的一个:如果您对效率不确定,请不要进行优化!首先以合理的方式编写程序,然后根据需要对其进行分析速度。当您知道它将减少算法的时间或空间复杂度时,或者如果它会在程序的计算密集型部分中显着减少常数因子,则优先级优化只是一个好主意。这里也不是这样的。
其次,函数应该采用所需数量的参数。这听起来像是重言式,它几乎是,但重点是减少传递给实际使用这些参数的函数的参数数量是没有意义的。如果 实际上不使用某些参数,请删除它们;如果在子表达式中一起使用参数组,则将它们作为单独的函数提取并传入结果;如果将一堆参数一起传递给多个函数,则将它们捆绑在一个记录类型中并将其作为单个参数传递;但是为了消除它们,不要试图消除参数。这毫无意义!
此外,从问题本身来看:
但是我需要这些参数是纯粹的,所以我不能以任何方式使用IO。因此,每次至少部分程序都必须重新编译。
纯参数不是。它们是不变的价值观。您可以在源代码中的其他位置定义它们,但在编译之后它们是固定且不可变的。如果程序需要访问编译后执行更改的参数,则 以使用I / O.这实际上是I / O的定义!
请记住,即使您需要在IO
计算中获取值,所有实际逻辑都可以在纯函数中完成,如下所示:
main :: IO ()
main = do x <- getParameter
let r = lotsOfCalculations x
print r
函数lotsOfCalculations
以及它使用的任何其他东西都是纯函数。 IO
的唯一用途是获取参数。
另外,为了更简洁,请注意上面的代码也可以写成main = getParameter >>= print . lotsOfCalculations
。
答案 1 :(得分:2)
使用阅读器monad,例如来自Control.Monad.Reader的Reader r
。然后使用runReader
运行计算。
您将模拟参数传递给runReader
,然后模拟的组件可以使用ask
和asks
访问它们。
(注意:这要求您将所有参数捆绑为单个数据类型。)
答案 2 :(得分:1)
除非你在解释器中运行这个程序,否则你必须在某个时候进入IO。最有可能通过主要功能,这是不纯的。
无论如何,只需将您的功能设计为纯粹的。在你的不纯函数中,你可以使用Maybe
monad来净化值,然后将它们传递(或不传递给Nothing)到你的纯函数中。
请记住,要从程序中获取任何类型的输出,它需要通过显式(例如主函数)或隐式(解释器)运行IO函数。
答案 3 :(得分:1)
尝试使用闭包
doCalculation params input = inner input where
inner = ... (references params variable)
inner2 = ... (references params variable)
一般来说,在Haskell中,当你试图违反纯度时,会发生不好的事情。例如,在unsafePerformIO
中包装随机数生成器调用意味着您不会获得随机数,因为它将开始重复计算(以意想不到的方式)。
此外,还有记录类型,因此您可以创建类似
的内容data Params = Params { name :: String, speed :: Double }