Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我可以让返回类型随参数变化,有点像F#中的sprintf吗?_F# - Fatal编程技术网

我可以让返回类型随参数变化,有点像F#中的sprintf吗?

我可以让返回类型随参数变化,有点像F#中的sprintf吗?,f#,F#,在F#核心库中,有些函数的特征似乎在编译时根据参数而改变: >sprintf“你好%i”;; val it:(int->string)= >sprintf“你好%s”;; val it:(字符串->字符串)= 是否可以实现具有此属性的我自己的函数 例如,我是否可以设计一个将字符串与变量组件匹配的函数: matchPath”/products/:string/:string“(乐趣(类别:string)(sku:string)->()) 匹配路径“/tickets/:int”(乐趣(id:int

在F#核心库中,有些函数的特征似乎在编译时根据参数而改变:

>sprintf“你好%i”;;
val it:(int->string)=
>sprintf“你好%s”;;
val it:(字符串->字符串)=
是否可以实现具有此属性的我自己的函数

例如,我是否可以设计一个将字符串与变量组件匹配的函数:

matchPath”/products/:string/:string“(乐趣(类别:string)(sku:string)->())
匹配路径“/tickets/:int”(乐趣(id:int)->())
理想情况下,我希望避免动态强制转换

有两个相关的F#特性使这样做成为可能

Printf格式字符串。编译器以特殊方式处理格式字符串,如
“hi%s”
。它们不仅限于
printf
,还可以以某种不同的方式使用库中的这些文件。这不允许您更改语法,但如果您愿意使用例如
“/products/%s/%d”
”指定路径,则可以使用此选项。Giraffe库定义,它使用此技巧进行请求路由:

let webApp =
    choose [
        routef "/foo/%s/%s/%i" fooHandler
        routef "/bar/%O" (fun guid -> text (guid.ToString()))
    ]
类型提供程序。另一种选择是使用F类型提供程序。使用参数化类型提供程序,您可以编写一个由文字字符串参数化的类型,并且其成员的类型由您基于文字字符串参数编写的某些F#代码生成。例如:

我调整了您的示例,使
r
是一个具有与字符串中的名称匹配的属性的对象,但是您也可以使用具有多个参数的lambda。尽管如此,如果您想指定这些匹配的类型,您可能需要一种更奇特的语法,如
“/product/[category:int]/[sku:string]”
——这只是一个必须在类型提供程序中解析的字符串,因此完全由您决定。

第一:是正确答案

但是。。。我也有同样的问题。
虽然我可以从概念上理解为“它必须是‘字符串格式的东西’或‘提供者的东西’”
在我尝试实现之前,我无法告诉自己我得到了什么
... 这花了我一点时间。
我用FSharp.Core和Giraffe作为指南
并以长颈鹿为灵感,提出了这个天真的要点/实现

顺便说一句,诀窍在于这一点的魔力
乐趣(格式:printformat'R)

open System.Text.regular表达式
//将格式模式转换为正则表达式模式
让rec存储模式=
功能
|“%”:c::tail->
匹配c
|‘我’->
设x,rest=toRegexPattern尾
(\d+)+x,其余
|‘s’->
设x,rest=toRegexPattern尾
(\w+)+x,其余
|x->
failwithf“%”%%c“未实现\n”x
|c::tail->
设x,rest=toRegexPattern尾
设r=c.ToString()|>Regex.Escape
r+x,其余
| [] -> "", []
//装卸厂
let内联处理程序(格式:printformat string)(解码:string list->'T)=
format.Value.ToCharArray()格式
|>数组列表
|>toRegexPattern
|>fst,句柄,解码
//活动模式
让(| RegexMatch | | |)模式输入=
设m=Regex.Match(输入,模式)
如果m.成功了那么
让价值观=
[对于正则表达式中的g(模式)。匹配(输入)。组执行
如果g.Success&&g.Name“0”,则产生g.Value]
一些价值观
其他的
没有一个
让getPattern(pattern,u,u)=pattern
让gethandler(0,handle,0)=handle
让getDecoder(u,u,decode)=解码
让路由器路径=
让我们来看看路线1=
处理程序“/xyz/%s/%i”
(乐趣(类别、身份证)->
//处理请求
sprintf“已处理:路由1:%s/%i”类别id)
(趣味价值观->
//转换匹配项
值|>List.item 0,
价值观
|>清单1.项目1
|>int32)
让我们看看路线2=
处理程序“/xyz/%i”
(fun(id)->sprintf“handled:route2:id:%i”id)//句柄
(趣味值->值|>List.head |>int32)//解码
//路由器
(将路径与
|RegexMatch(getPattern route2)值->
价值观
|>getDecoder路由2
|>gethandler路由2
|RegexMatch(getPattern route1)值->
价值观
|>getDecoder路由1
|>gethandler路由1
|_u->failwith“No Match”)
|>printf“路由:%A\n”
让主argv=
尝试
让arg=argv |>Array.skip 1 |>Array.head
路由器参数
0//返回整数退出代码
具有
|失败消息->
eprintf“错误:%s\n”消息
-1

看,我认为这是因为从调用的
doPrintf
中使用了该选项。您可能也想看看类型提供程序在F#中的工作方式。忘记了链接,因此不允许我编辑注释:
type TempRegex = Regex< @"^(?<Temperature>[\d\.]+)\s*°C$", noMethodPrefix = true >
TempRegex().Match("21.3°C").Temperature.TryValue
MatchPath<"/products/:category/:sku">.Match(fun r -> 
  printfn "Got category %s and sku %s" r.Category r.Sku)