如何将两个函数调用合并为一个?

2024-04-08

我想合并以下几行:

let result1 = add (numbers, ",")
let result2 = add (numbers, "\n")

变成这样的东西:

let resultX = add (numbers, ",") |> add (numbers, "\n")

我可以编写这样的函数吗?

NOTE:

我正在学习 F#,如果这个问题看起来很愚蠢,我深表歉意。

代码如下:

module Calculator

open FsUnit
open NUnit.Framework
open System

let add (numbers:string) =

    let add (numbers:string) (delimiter:string) =
        if (numbers.Contains(delimiter)) then
            numbers.Split(delimiter.Chars(0)) |> Array.map Int32.Parse
                                              |> Array.sum
        else 0

    let result1 = add numbers ","
    let result2 = add numbers "\n"

    if (result1 > 0 || result2 > 0) then 
        result1 + result2

    else let _ , result = numbers |> Int32.TryParse
         result

Tests:

[<Test>]
let ``adding empty string returns zero`` () =

    let result = add ""
    result |> should equal 0

[<Test>]
let ``adding one number returns number`` () =

    let result = add "3"
    result |> should equal 3

[<Test>]
let ``add two numbers`` () =

    let result = add "3,4"
    result |> should equal 7

[<Test>]
let ``add three numbers`` () =

    let result = add "3,4,5"
    result |> should equal 12

[<Test>]
let ``line feeds embedded`` () =

    let result = add "3\n4"
    result |> should equal 7

UPDATED

我收到以下错误:

类型“int”与类型“string”不匹配

let add (numbers:string) =

    let add (numbers:string) (delimiter:string) =
        if (numbers.Contains(delimiter)) then
            numbers.Split(delimiter.Chars(0)) |> Array.map Int32.Parse
                                              |> Array.sum
        else 0

let resultX = numbers |> add ","
                      |> add "\n"

实施反馈:

let add (numbers:string) =

    let add (numbers:string) (delimiters:char array) =
        if numbers.Length = 0 then 0
        else numbers.Split(delimiters) |> Array.map Int32.Parse
                                       |> Array.sum
    let delimiters = [|',';'\n'|]
    add numbers delimiters

这不是一个确切的答案,因为我不确定你的意思,但它应该给你一些想法。

let add01 (numbers:string) =
    let delimiters : char array = [|',';'\n'|]
    let inputArray : string array = numbers.Split(delimiters)
    let numbers : string list = Array.toList(inputArray)
    let rec add (numbers : string list) (total : int) : int =
        match (numbers : string list) with
        | ""::t ->
            add t total
        | h::t -> 
            let number =  System.Int32.Parse h
            let total = total + number
            add t total
        | [] -> total        
    add numbers 0

let numbers = "1,2,3\n4,5,6\n\n"
let result = add01 numbers

当给出以下代码时,会出现以下错误,为什么?

// Type mismatch. Expecting a
//     int -> 'a    
// but given a
//     string -> int    
// The type 'int' does not match the type 'string'
let result = numbers |> add ","
                     |> add "\n"

由于这是一个错误,表明两种类型不同意,因此需要理解类型推断 https://en.wikipedia.org/wiki/Type_inference以及如何解决此类问题。 我不会在这里解释类型推断,因为这本身就是一个很大的主题,但是我将给出一个在大多数情况下成功解决此类错误的模式示例。

当 F# 编译代码时,它会在执行类型检查之前使用类型推断将缺少的类型添加到函数和值中,而失败的正是类型检查。因此,为了查看编译器对类型的看法,我们将在此处手动添加它们,并剔除代码中不会导致问题的部分,从而让我们知道错误的原因,然后希望在某些事情中变得明显可以修复。

唯一具有类型的东西是:

  • result
  • =
  • 数字
  • |>
  • add
  • ","
  • "\n"

值的类型很简单:

  • 结果:整数
  • 数字:字符串
  • “,“ : 细绳
  • “\n”:字符串

我不记得 F# 将 equals (=) 视为函数,但这里是如何看待它的。
= : 'a -> 'a

管道运营商

let (|>) (x : 'a) f = f (x : 'a)  

为了解决这个问题,只需将管道运算符视为句法糖 https://en.wikipedia.org/wiki/Syntactic_sugar.
请参阅下面的示例以更好地理解。

添加功能
添加:字符串 -> 字符串 -> int

因此,让我们将错误细化到其本质。

//Type mismatch. Expecting a
//    int -> 'a    
//but given a
//    string -> int    
//The type 'int' does not match the type 'string'
let result = numbers |> add ","
                     |> add "\n"

将类型签名添加到值中并验证是否得到相同的错误。 这就是类型推断要做的事情,我们手动完成。

//Type mismatch. Expecting a
//    int -> int    
//but given a
//    string -> int    
//The type 'int' does not match the type 'string'
let (result : int) = (numbers : string) |> add ("," : string) 
                     |> add ("\n" : string)

现在将代码视为可以因式分解的数学表达式。

分解出第一个管道运算符并验证我们是否得到了相同的错误。 请注意,错误现在只是 r2 的一部分

//Expecting a
//    int -> 'a    
//but given a
//    string -> int    
//The type 'int' does not match the type 'string'
let (result : int) = 
    let r1 = (numbers : string) |> add ("," : string) 
    let r2 = r1 |> add ("\n" : string)
    r2

撤消第二个管道运算符的语法糖并验证我们是否得到了相同的错误。 请注意,错误现在只是 r2 的一部分;特别是 r1 参数

//This expression was expected to have type
//    string    
//but here has type
//    int
let (result : int) = 
    let r1 = (numbers : string) |> add ("," : string) 
    let r2 = add ("\n" : string) r1
    r2

将类型添加到 r1 并验证我们得到相同的错误。

//This expression was expected to have type
//    string    
//but here has type
//    int   
let (result : int) = 
    let (r1 : int) = (numbers : string) |> add ("," : string) 
    let r2 = add ("\n" : string) r1
    r2

此时错误应该是显而易见的。 第一个管道运算符的结果是int并作为第二个参数传递给 add 函数。 add 函数需要一个string对于第二个参数,但给出了int.


为了更好地理解管道运算符的工作原理,我为此演示创建了一个等效的用户定义运算符。

这些是用于演示的一些辅助函数。

let output1 w =
    printfn "1: %A" w

let output2 w x =
    printfn "1: %A 2: %A" w x

let output3 w x y =
    printfn "1: %A 2: %A 3: %A" w x y

let output4 w x y z =
    printfn "1: %A 2: %A 3: %A 4: %A" w x y z

使用不带管道运算符的输出函数。

output1 "a"  
1: "a"  

output2 "a" "b"  
1: "a" 2: "b"  

output3 "a" "b" "c"  
1: "a" 2: "b" 3: "c"  

output4 "a" "b" "c" "d"  
1: "a" 2: "b" 3: "c" 4: "d"  

请注意,输出的顺序与输入的顺序相同。

将输出函数与管道运算符一起使用。

// 让 (|>) x f = fx

"a" |> output1  
1: "a"  

"a" |> output2 "b"  
1: "b" 2: "a"  

"a" |> output3 "b" "c"  
1: "b" 2: "c" 3: "a"  

"a" |> output4 "b" "c" "d"  
1: "b" 2: "c" 3: "d" 4: "a"  

请注意,由于使用了管道运算符 (|>),输出函数的最后一个参数是管道运算符 (“a”) 左侧的值。

// 参见第 3.7 节F#规范 http://fsharp.org/specs/language-spec/4.0/FSharpSpec-4.0-latest.pdf关于如何定义用户定义的运算符。

将输出函数与用户定义的管道运算符一起使用。

let (@.) x f = f x  

"a" @. output1  
1: "a"  

"a" @. output2 "b"  
1: "b" 2: "a"  

"a" @. output3 "b" "c"  
1: "b" 2: "c" 3: "a"  

"a" @. output4 "b" "c" "d"  
1: "b" 2: "c" 3: "d" 4: "a"  
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将两个函数调用合并为一个? 的相关文章

  • F# 图表示例

    我想使用内置功能或免费库在 F 中做一些基本的图表 我会对一个非常基本的例子感到非常非常满意 如果可能的话 饼图 示例数据 John 34 Sara 30 Will 20 Maria 16 其中整数是饼图中要表示的百分比 我最近安装了 VS
  • Scala 相当于 F# 中的 |> 或 Clojure 中的 ->>

    在 Scala 中 当我有这个表达式时 f1 f2 f3 p 有没有一种方法可以让我使用类似的东西 F p gt f3 gt f2 gt f1 还是 Clojure gt gt p f3 f2 f1 Scala 中没有相当于 F 的管道运算
  • F# 类型函数和 [] 属性

    这两个 F 类型函数有什么区别 let defaultInstance1 lt a when a new unit gt a gt new a
  • 没有带有常量“模板参数”的 F# 泛型?

    我突然想到 F 泛型似乎不接受常量值作为 模板参数 假设有人想创建一种类型RangedInt这样 它的行为类似于 int 但保证只包含整数值的子范围 一种可能的方法是建立受歧视的工会 类似于 type RangedInt Valid of
  • F# 设置带有参数的 SQLCommand 的最佳方法

    我的 F 程序需要与 SQL Server 通信 在一部分中我有这样的事情 let workFlowDetailRuncommand new SqlCommand query econnection workFlowDetailRuncom
  • F# 中使用抽象类还是接口?

    从 C 背景开始摸索 F 在 C 中 决定何时使用接口和何时使用抽象类有明显的区别 在 F 中 我发现两者几乎合而为一 我知道 就 CLR 而言 F 中的做法与 C 中的做法相同 但是在 F 中编程时使用的 最佳实践 是什么 我应该完全避免
  • 在 Blazor 中显示计时器

    我正在尝试在服务器端 Blazor 应用程序中显示倒计时器 我的代码同时使用 F 和 C 语言 该代码在某种程度上可以工作 但计时器永远不会按预期停止 并且计时器显示偶尔不会呈现所有数字 这是我第一次尝试 Blazor 服务器端应用程序 我
  • Async.TryCancelled 不适用于 Async.RunSynchronously

    我尝试创建一个根据用户交互更新 UI 的代理 如果用户单击按钮 则应刷新 GUI 模型的准备需要很长时间 因此希望如果用户单击其他按钮 则取消准备并开始新的准备 到目前为止我所拥有的 open System Threading type p
  • 如何在插件场景中实现程序集绑定重定向?

    我有一个plugin P延伸和application A NET40 我无法控制 P 程序集 NET40 有一个shared dependency D NET35 P和D都依赖于FSharp Core 但版本不同 P是针对FSharp Co
  • 在 F# 中“合并”受歧视的联合?

    继从这个问题 https stackoverflow com questions 53506325 result vs raise in f async 我在组合不同类型时遇到问题Result类型在一起 以下是一个人为的示例 不是真实的代码
  • 如何在 F# 中将对象转换为泛型类型列表

    在下面的代码片段中 我的目的是将 System Object 可能是 FSharpList 转换为它所持有的任何泛型类型的列表 match o with list lt gt gt addChildList o gt list lt gt
  • F# 在类型提供程序内的类型扩展函数中生成类型

    我有以下问题 在我的类型提供程序中 我需要使用一个返回此泛型类型实例的方法来扩展我之前定义的泛型类型 我的意思是 假设我们有 type receiveType lt a gt class val Next int val Type stri
  • 如何在 F# 中捕获任何异常(System.Exception)而不发出警告?

    我试图捕获异常 但编译器给出警告 此类型测试或向下转型将始终保持 let testFail try printfn Ready for failing failwith Fails with System ArgumentException
  • 管道序列中的异常处理

    我正在开发一个基本的 2D CAD 引擎 管道操作符显着改进了我的代码 基本上 有几个函数从空间中的点 x y 开始 并在多次移动操作后计算最终位置 let finalPosition startingPosition gt moveByL
  • F# 获取随机数列表

    我正在尝试用随机数填充列表 但很难获得随机数部分 我现在打印出一个随机数 10 次 我想要的是打印出 10 个不同的随机数 let a new System Random Next 1 1000 let listOfSquares for
  • F# 编码练习

    我一直在 Visual Studio 2010 中涉足 F 我是一名在 C 和 Java 等面向对象语言方面拥有更多代码 架构设计经验的开发人员 为了扩展我的技能并帮助做出更好的决策 我正在尝试使用不同的语言来做不同的事情 特别是掌握使用函
  • F# 对于 OO 或命令式来说缺少什么? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 使用 SqlBulkCopy 和 F# 在 SQL 中导出矩阵

    我想将大量数据从 F 传输到 SQL 表 基本上我的 F 代码创建了一个三列矩阵 UserID ProductID and price 和N行 我想将其 复制 粘贴 到数据库中 我尝试了多种选择 但最终 从 F 传输数据非常慢 10000
  • 从 C# 调用高阶 F# 函数

    给定 F 高阶函数 在参数中采用函数 let ApplyOn2 f int gt int f 2 和 C 函数 public static int Increment int a return a 我怎么打电话ApplyOn2 with I
  • “不等于”的 F# 语法是什么?

    在 C 代码中 它会是这样的 if c 0 some code 那么在 F 中呢 From MSDN 有关 F 算术运算符的页面 http msdn microsoft com en us library dd469493 aspx 看起来

随机推荐