如何执行此F#函数 [英] How to execute this F# function

查看:84
本文介绍了如何执行此F#函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图以多种方式执行以下功能,但始终出错. 那么我该如何执行constructQuery:

I tried to execute the following function in multiple ways, but it was always in error. So how do i execute constructQuery :

type PersonName =
| FirstOnly of string
| LastOnly of string
| FirstLast of string * string

let constructQuery personName = 
    match personName with
    | FirstOnly(firstName) -> printf "May I call you %s?" firstName
    | LastOnly(lastName) -> printf "Are you Mr. or Ms. %s?" lastName
    | FirstLast(firstName, lastName) -> printf "Are you %s %s?" firstName lastName

-编辑-.

我尝试过这样调用函数:

I have tried calling the function like this:

constructQuery "himekami"
constructQuery ("himekami" : PersonName.FirstOnly)
constructQuery PersonName.FirstOnly("himekami")

产生的错误是这样的:

Analyzer.fs(12,17): error FS0001: This expression was expected to have type
PersonName    

但是这里有类型 字符串

but here has type string

这是因为我不太了解F#中类型"的工作方式.

This is because i don't quite understand the way "type" in F# works.

推荐答案

我想问题是如何构造PersonName对象(因为这些是函数的输入).

I guess the question is how to construct PersonName objects (as those are the input for your function).

这很容易-只需使用构造器FirstOnlyLastOnlyFirstLast之一:

This is quite easy - just use one of the constructors FirstOnly, LastOnly or FirstLast:

let firstOnly = FirstOnly "Tom"
let lastOnly  = LastOnly "Hengs"
let firstLast = FirstLast ("Tom", "Hengs")

,您可以像这样使用它们:

and you can use them like this:

constructQuery firstOnly
constructQuery lastOnly
constructQuery firstLast

背景

您会看到PersonName是一个代数数据类型,具有3个构造函数,而constructQuery与其匹配,这是它们的唯一参数.在VisualStudio(或MonoDevelop)中,您应该能够获得有关此部分每个部分类型的工具提示-您应该一直这样做,因为类型是理解的重要部分.

background

You see PersonName is an algebraic datatype with it's 3 constructors and the constructQuery matches it's only parameter for them. In VisualStudio (or MonoDevelop) you should be able to get a tooltip with the types for each part of this - you should do this all the times, because types are a big part understanding.

您可以使用管道操作器|>并一次性完成该操作:

you can use the pipe-operator |> and do this in one go:

FirstOnly "Tom"
|> constructQuery

当然,您也可以在不使用此运算符的情况下使用它:

of course you can use it without this operator too:

constructQuery (LastOnly "Hengs")

但是在这里您需要括号,因为没有它们,您会将函数 LastOnly(是的,这是函数String -> PersonName)插入函数constructQuery中,然后像这个:

but here you need the parens because without them you would plug the function LastOnly (and yes this is a function String -> PersonName) into the function constructQuery and then apply the string like this:

constructQuery LastOnly "Hengs" = (constructQuery LastOnly) "Hengs" // error: compiler complains about mismatched types

因为LastOnly实际上是一个函数(不幸的是C#构造函数不是这种情况),所以您也可以做一些很酷的事情:

because LastOnly is really a function (sadly this is not the case for C# constructors) you can do cool stuff like this too:

// Pipes all the way
"Hengs" |> LastOnly |> constructQuery

// this is another function String -> PersonName
let constructFromLastOnly = LastOnly >> constructQuery

// you can call it like this
constructFromLastOnly "Hengs"

// etc. ... imagine

另一种选择是使用向后管道<|(不是惯用的):

another alternative is to use the backwards pipe <| (not so idiomatic):

constructQuery <| LastOnly "Hengs"

您也不需要parens的地方

where you don't need the parens either

我鼓励您(即使编译器确实不需要它)提供顶级函数的类型(您希望从程序的其他部分使用的thouse):

I would encourage you (even if the compiler don't really needs it) to give the types for top-level functions (thouse you want to use from other parts of your program):

let constructQuery (personName : PersonName) : () =
   match personName with
   // ...

除了呼叫match之外,您是否还真的不需要personName吗? 这是如此普遍,以至于有另一种/更短的方式来写:

Did you see that you don't really need personName besides the call to match? This is so common that there is another/shorter way to write this:

let constructQuery = function
    | FirstOnly(firstName) -> printf "May I call you %s?" firstName
    | LastOnly(lastName) -> printf "Are you Mr. or Ms. %s?" lastName
    | FirstLast(firstName, lastName) -> printf "Are you %s %s?" firstName lastName

或带有签名:

let constructQuery : PersonName -> () = 
    function
    | FirstOnly(firstName) -> printf "May I call you %s?" firstName
    | LastOnly(lastName) -> printf "Are you Mr. or Ms. %s?" lastName
    | FirstLast(firstName, lastName) -> printf "Are you %s %s?" firstName lastName

最后-我不喜欢您在其中混入printf的事实. 请参见函数返回单元()永远不会纯粹,您会混合考虑.为什么不这样:

And finally - I don't like the fact that you mix printf in there. See a function returning unit () is never pure and you mix concerns. Why not like this:

let constructQuery : PersonName -> string = 
    function
    | FirstOnly(firstName) -> sprintf "May I call you %s?" firstName
    | LastOnly(lastName) -> sprintf "Are you Mr. or Ms. %s?" lastName
    | FirstLast(firstName, lastName) -> sprintf "Are you %s %s?" firstName lastName

并像这样使用它:

FirstOnly "Tom"
|> constructQuery
|> Console.WriteLine

因此您可以重用它,例如在WPF应用程序中或在控制台不可用的日志记录方案中.

so you can reuse it for example in a WPF app or in a logging scenario where the console is not avaiable.

这篇关于如何执行此F#函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆