jam*_*o00 8 .net f# functional-programming
我一直在玩函数式语言(特别是F#),我真的很喜欢整个不可变/概念.但是,我对你如何用函数式语言表示有状态的东西感到有些迷茫.
例如,如何在函数式语言中重写以下内容?(任何功能语言都很好......只需要绕过它)
class state
{
int current_time;
bool is_completed() {
return current_time() - start_time > 30 seconds
}
double get_progress() {
return (current_time() - start_time) / 30 seconds
}
void start() {
start_time = current_time();
}
}
void main() {
state s;
s.start();
while(s.is_completed() == false) {
print s.get_progress();
}
print "finished";
}
Run Code Online (Sandbox Code Playgroud)
您的示例包含一些在函数式语言中有所不同的方法:
current_time用来获取当前时间,但这不是一个纯函数(它取决于一些全局变化的状态).在纯函数式语言(Haskell)中,这是不允许的(并且你必须使用monad),但是大多数不纯的函数语言(F#,OCaml)都允许这样做.main函数使用循环 - 通常不鼓励在函数式语言中使用循环(尽管有些人支持它们).惯用的F#解决方案将处理第一个和最后一个点,如下所示:
let currentTime() =
System.DateTime.Now
type State(startTime) =
static member Start() =
State(currentTime())
member x.IsCompleted =
(currentTime() - startTime).TotalSeconds > 30.0
member x.Progress =
(currentTime() - startTime).TotalSeconds / 30.0
let main() =
let s = State.Start()
let rec loop () =
if not s.IsCompleted then
printf "%A" s.Progress
loop ()
loop ()
printf "finished"
Run Code Online (Sandbox Code Playgroud)
State从某种意义上说,类型是不可变的,它永远不会改变其本地字段的值.它不是纯粹的功能,因为它取决于(改变)当前时间,但这不是F#中的问题(你只需要知道这一点).如果你需要一些修改状态的方法(你不需要),那么该方法将返回一个新的实例State(就像.NET一样string).
该main函数是使用递归而不是循环编写的 - 在这种情况下,它并不重要(循环在F#中也可以).使用递归的关键是您可以将当前状态作为参数传递,并在进行递归调用时使用新实例(这实际上会在计算期间更改当前状态).