Recursion 为什么赢了';难道我的电脑不能让我问候我的顾客吗?

Recursion 为什么赢了';难道我的电脑不能让我问候我的顾客吗?,recursion,f#,Recursion,F#,我正在写一份申请书来取代我们的技术支持部门。当客户需要技术支持时,我们只需给他邮寄一张包含此应用程序的软盘,他只需将软盘放入电脑孔中安装即可。他们只需输入问题,程序就会输出解决方案 我试着用F写,但F不喜欢。我编写了这个简单的递归函数,它向客户显示问候信息,但F#告诉我“不,这段代码不好”。我很有信心我的代码是好的,也不明白为什么F#认为它如此糟糕 这是我的代码: open System let rec GreetCustomer message = let DisplayMessag

我正在写一份申请书来取代我们的技术支持部门。当客户需要技术支持时,我们只需给他邮寄一张包含此应用程序的软盘,他只需将软盘放入电脑孔中安装即可。他们只需输入问题,程序就会输出解决方案

我试着用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#程序,使其不会抱怨无限类型?

我在评论中链接的问题详细阐述了这一点。在F#中有很多方法可以做到这一点,但是没有一种方法可以提供您想要的语法。下面的答案和它得到的一样好


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

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


键入Inf我在评论中链接的问题详细阐述了这一点。在F#中有很多方法可以做到这一点,但是没有一种方法可以提供您想要的语法。下面的答案和它得到的一样好


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

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


键入Inf丹尼尔链接到的答案应该告诉你如何解决这个问题


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

Daniel链接的答案应该告诉您如何解决该问题


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

“我们将给他发一张软盘”-你肯定是在开玩笑。计算机洞?这真是太好笑了。
但是F#告诉我“不,这个代码不好”
-你能引用一下编译器的错误代码吗?我想你对信息的地区翻译让谷歌很难查到日期:不是4月1日,那这是什么?“我们会给他寄一张软盘”-你肯定在开玩笑。电脑洞?这真是太好笑了。
但是F#告诉我“不,这个代码不好”
-你能引用一下编译器的错误代码吗?我想你对信息的区域翻译让谷歌很难查到日期:不是4月1日,那么这是什么?无限shminfinite!F#应该能够更优雅地处理无限类型。这感觉与更高级的类型有些关联,我希望看到它们和循环定义都得到支持。@Peter:这要求.NET本身支持无限类型。不要因为.NET的限制而责怪F.-]@ildjarn-没有任何东西阻止F#在.NET中执行此操作-编译器为函数值创建
FSharpFunc
的子类,因此它可以创建一个子类
Inf@kvb我只是举了一个现实场景的例子,证明了这一点无限有限!F#应该能够更优雅地处理无限类型。这感觉与更高级的类型有些关联,我希望看到它们和循环定义都得到支持。@Peter:这要求.NET本身支持无限类型。不要因为.NET的限制而责怪F.-]@ildjarn-没有任何东西阻止F#在.NET中执行此操作-编译器为函数值创建
FSharpFunc
的子类,因此它可以创建一个子类
Inf@kvb我只是举了一个现实场景的例子,证明了这一点
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