F# 如何调用用作函数参数的函数值?
如何调用用作函数参数的函数值? 具体来说,我的目标是利用函数的一个参数,其中的参数实际上是一个函数 在我的例子中,我试图实现一个用于记录数据的接口 这是我的代码:F# 如何调用用作函数参数的函数值?,f#,F#,如何调用用作函数参数的函数值? 具体来说,我的目标是利用函数的一个参数,其中的参数实际上是一个函数 在我的例子中,我试图实现一个用于记录数据的接口 这是我的代码: let logToFile (filePath:string) (message:string) = let file = new System.IO.StreamWriter(filePath) file.WriteLine(message) file.Close() let makeInitialDepo
let logToFile (filePath:string) (message:string) =
let file = new System.IO.StreamWriter(filePath)
file.WriteLine(message)
file.Close()
let makeInitialDeposit deposit =
let balance = deposit |> insert []
sprintf "Deposited: %f" balance
let logDeposit deposit (log:'medium ->'data -> unit) =
deposit |> makeInitialDeposit
|> log
let logDeposit deposit (log:'medium ->'data -> unit) =
deposit |> makeInitialDeposit
|> log
let logDeposit deposit (log:'medium ->'data -> unit) medium =
deposit |> makeInitialDeposit
|> log medium
注意以下功能:
let logToFile (filePath:string) (message:string) =
let file = new System.IO.StreamWriter(filePath)
file.WriteLine(message)
file.Close()
let makeInitialDeposit deposit =
let balance = deposit |> insert []
sprintf "Deposited: %f" balance
let logDeposit deposit (log:'medium ->'data -> unit) =
deposit |> makeInitialDeposit
|> log
let logDeposit deposit (log:'medium ->'data -> unit) =
deposit |> makeInitialDeposit
|> log
let logDeposit deposit (log:'medium ->'data -> unit) medium =
deposit |> makeInitialDeposit
|> log medium
我在日志函数中遇到编译错误:
此构造导致代码不像
类型注释。类型变量“medium”已被约束为
键入“string”
我知道makeInitialDeposit返回字符串。
但是,该字符串类型映射到泛型类型“数据”。
因此,泛型可以是任何类型,对吗
然后我尝试提供媒体(即文件)参数:
let logToFile (filePath:string) (message:string) =
let file = new System.IO.StreamWriter(filePath)
file.WriteLine(message)
file.Close()
let makeInitialDeposit deposit =
let balance = deposit |> insert []
sprintf "Deposited: %f" balance
let logDeposit deposit (log:'medium ->'data -> unit) =
deposit |> makeInitialDeposit
|> log
let logDeposit deposit (log:'medium ->'data -> unit) =
deposit |> makeInitialDeposit
|> log
let logDeposit deposit (log:'medium ->'data -> unit) medium =
deposit |> makeInitialDeposit
|> log medium
然后我的错误被更新为:
let logToFile (filePath:string) (message:string) =
let file = new System.IO.StreamWriter(filePath)
file.WriteLine(message)
file.Close()
let makeInitialDeposit deposit =
let balance = deposit |> insert []
sprintf "Deposited: %f" balance
let logDeposit deposit (log:'medium ->'data -> unit) =
deposit |> makeInitialDeposit
|> log
let logDeposit deposit (log:'medium ->'data -> unit) =
deposit |> makeInitialDeposit
|> log
let logDeposit deposit (log:'medium ->'data -> unit) medium =
deposit |> makeInitialDeposit
|> log medium
此构造导致代码不像
类型注释。类型变量“数据”已被约束为
键入“string”
我的目标
最终,我只希望有一个名为log的接口,并传入该接口的实现(即logToFile)
根据我最初的解释,有关于如何解释编译错误的指导吗
插入函数依赖项
let getBalance coins =
coins |> List.fold (fun acc d -> match d with
| Nickel -> acc + 0.05
| Dime -> acc + 0.10
| Quarter -> acc + 0.25
| OneDollarBill -> acc + 1.00
| FiveDollarBill -> acc + 5.00) 0.00
let insert balance coin =
coin::balance |> getBalance
首先,您传入一个字符串,如
“deposition:0.25”
作为路径名,这似乎有些奇怪。您可能希望将message
作为第一个参数,将filePath
作为logToFile
的第二个参数。相应地,log
将成为'data->'medium->unit
要解决这个问题,编译器错误的问题是makeInitialDeposit
返回一个字符串,然后将该结果导入log
时,约束就会发生。使其工作的一种方法是向logDeposit
添加另一个参数,以将字符串转换为数据,如下所示:
let logDeposit deposit (log: 'data ->'medium-> unit) (stringConverter: string -> 'data) =
deposit |> makeInitialDeposit
|> stringConverter
|> log
let valueOf = function
| Nickel -> 0.05m
| Dime -> 0.10m
| Quarter -> 0.25m
| OneDollarBill -> 1.00m
| FiveDollarBill -> 5.00m
let totalValue coins =
coins |> List.fold (fun acc coin -> acc + valueOf coin) 0.0m
let insert coins coin = coin::coins // returns Coin list
let makeInitialDeposit deposit = insert [] deposit // returns Coin list
使用类似于的方法,假设您传入从字符串到int的适当转换器,让dummyLog(a:int)(b:string)=()
可以工作。首先,您传入一个类似于的字符串作为路径名似乎有些奇怪。您可能希望将message
作为第一个参数,将filePath
作为logToFile
的第二个参数。相应地,log
将成为'data->'medium->unit
要解决这个问题,编译器错误的问题是makeInitialDeposit
返回一个字符串,然后将该结果导入log
时,约束就会发生。使其工作的一种方法是向logDeposit
添加另一个参数,以将字符串转换为数据,如下所示:
let logDeposit deposit (log: 'data ->'medium-> unit) (stringConverter: string -> 'data) =
deposit |> makeInitialDeposit
|> stringConverter
|> log
let valueOf = function
| Nickel -> 0.05m
| Dime -> 0.10m
| Quarter -> 0.25m
| OneDollarBill -> 1.00m
| FiveDollarBill -> 5.00m
let totalValue coins =
coins |> List.fold (fun acc coin -> acc + valueOf coin) 0.0m
let insert coins coin = coin::coins // returns Coin list
let makeInitialDeposit deposit = insert [] deposit // returns Coin list
使用类似于的方法,假设您将适当的转换器从字符串传递到int,让dummyLog(a:int)(b:string)=()
可以工作。问题是您已经定义了日志:'medium->'数据->单元
然后获取deposit |>makeInitialDeposit
的结果,其类型为string
,并将其导入log
函数。然后,编译器从逻辑上推断出'medium=string
如果在logDeposit
函数中接受一个'medium
参数,则只需将该推断沿着一个步骤移动,deposit |>makeInitialDeposit
仍然是一个字符串
,因此现在'data=string
我认为您正在挣扎,因为这些函数不能很好地为您的域建模,您的日志逻辑正在泄漏到代码的其余部分
为什么makeInitialDeposit
返回字符串
为什么getBalance
返回float
但insert
接受Coin list
作为其balance
参数
首先,我将创建一个日志函数,该函数接受三个参数:
let logToFile (filePath:string) (formatf : 'data -> string) data =
use file = new System.IO.StreamWriter(filePath)
file.WriteLine(formatf data)
data
它的类型为filePath:string->(formatf:'data->string)->(data:'data)->data
。它接受一个要登录到的路径,一个将'data
类型的内容格式化为字符串的函数,以及一些要登录到文件的'data
。最后,它返回您提供的未更改的数据
参数。原则上,这意味着您可以在代码的任何位置插入任意值的日志记录
然后,我在域中设置了一些函数,如下所示:
let logDeposit deposit (log: 'data ->'medium-> unit) (stringConverter: string -> 'data) =
deposit |> makeInitialDeposit
|> stringConverter
|> log
let valueOf = function
| Nickel -> 0.05m
| Dime -> 0.10m
| Quarter -> 0.25m
| OneDollarBill -> 1.00m
| FiveDollarBill -> 5.00m
let totalValue coins =
coins |> List.fold (fun acc coin -> acc + valueOf coin) 0.0m
let insert coins coin = coin::coins // returns Coin list
let makeInitialDeposit deposit = insert [] deposit // returns Coin list
然后,我可以使用这些函数,在任意点插入日志:
let balance =
makeInitialDeposit OneDollarBill
|> logToFile "file.txt" (sprintf "Initial Deposit: %A")
|> totalValue
|> logToFile "file2.txt" (sprintf "Balance : $%M")
这种方法使您可以在域中进行日志记录,而不是围绕日志记录构建域。问题在于您已经定义了log:'medium->'data->unit
然后获取deposit |>makeInitialDeposit
的结果,其类型为string
,并将其导入log
函数。然后,编译器从逻辑上推断出'medium=string
如果在logDeposit
函数中接受一个'medium
参数,则只需将该推断沿着一个步骤移动,deposit |>makeInitialDeposit
仍然是一个字符串
,因此现在'data=string
我认为您正在挣扎,因为这些函数不能很好地为您的域建模,您的日志逻辑正在泄漏到代码的其余部分
为什么makeInitialDeposit
返回字符串
为什么getBalance
返回float
但insert
接受Coin list
作为其balance
参数
首先,我将创建一个日志函数,该函数接受三个参数:
let logToFile (filePath:string) (formatf : 'data -> string) data =
use file = new System.IO.StreamWriter(filePath)
file.WriteLine(formatf data)
data
它的类型