为什么我的电脑不能让我问候我的客户?

时间:2011-10-18 20:45:10

标签: recursion f#

我正在编写一份申请来取代我们的技术支持部门。当客户需要技术支持时,我们只需向他发送一张包含此应用程序的软盘,然后将其放入计算机孔并安装即可。他们只输入他们的问题,程序将输出解决方案。

我尝试用F#编写,但F#不喜欢它。我写了这个简单的递归函数,向客户显示一条问候语,但F#告诉我“不,这段代码很糟糕”。我非常有信心我的代码很好,并且无法弄清楚为什么F#认为它太糟糕了。

这是我的代码:

open System

let rec GreetCustomer message =
    let DisplayMessage message =
        Console.WriteLine(message + " " : string) |> ignore
        GreetCustomer
    DisplayMessage(x)

Console.WriteLine("Please do the needful by telling us your name?");
let CustomerName = Console.ReadLine()

GreetCustomer("Hello,")(CustomerName)("!")("How")("to")("help")("you")("today?")

和F#告诉我

  

类型不匹配。期待'a但给定'b - > 'a当统一''a'和''b - >时,结果类型将是无限的。 'A'

当然,结果类型是无限的。我希望能够将方法调用链接到无限次。我不明白为什么F#不喜欢无限类型;我可以在Javascript中编写相同的程序,没有任何问题:

GreetCustomer = function(message) {
  DisplayMessage = function(message) {
    document.write(message + " ");
    return GreetCustomer; 
  };
  return DisplayMessage(message); 
};

CustomerName = prompt("Please do the needful by telling us your name?");

GreetCustomer("Hello,")(CustomerName)("!")("How")("to")("help")("you")("today?");

并且它具有我想要的输出:

  彼得,你好!今天如何帮助你?

如果它在Javascript中运行,肯定必须有一种方法可以在F#中进行。

如何修复我的F#程序,以免它抱怨无限类型?

2 个答案:

答案 0 :(得分:4)

我在评论中提到的问题详细阐述了这个问题。有很多方法可以在F#中执行此操作,但没有一种方法可以为您提供所需的语法。以下答案尽可能好。

https://stackoverflow.com/questions/2679547/function-which-returns-itself/2684005#2684005
https://stackoverflow.com/questions/2679547/function-which-returns-itself/2679578#2679578

简而言之,这是类型推断的限制。正如编译器抱怨的那样,返回自身的函数的类型无法解决;它是无限的。

修改

这是我首选的解决方法(结合我链接的问题的答案):

type Inf<'T> = delegate of 'T -> Inf<'T>

let rec makeInfinite f = 
  fun x -> 
    f x |> ignore
    Inf(makeInfinite f)

let (+>) (inf:Inf<_>) arg = inf.Invoke(arg)

let GreetCustomer = makeInfinite (printf "%s")

GreetCustomer "Hello " +> "there, " +> "how " +> "are " +> "you?" |> ignore

答案 1 :(得分:2)

Daniel与之相关的答案应告诉您如何解决问题。

原则上,我认为F#可以根据您的定义推断出('b -> 'a) as 'a这样的类型(这不是有效的F#语法)。相关语言OCaml提供-rectypes option以允许编译器推断这样的循环定义,但据我所知,默认情况下不启用该标志,因为推断的循环类型几乎总是指示程序员已经创建了错误。