如何执行此F#函数 [英] How to execute this F# function
问题描述
我试图以多种方式执行以下功能,但始终出错. 那么我该如何执行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).
这很容易-只需使用构造器FirstOnly
,LastOnly
或FirstLast
之一:
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屋!