gpt4 book ai didi

f# - 可能的 F# 类型推断限制

转载 作者:行者123 更新时间:2023-12-02 22:35:21 25 4
gpt4 key购买 nike

我很确定我遇到了某种限制,但我不明白:

type IRunner = 
abstract member Run : (string -> 'a) -> 'a
type T() =
let run4 doFun = doFun "4"
let run5 doFun = doFun "5"
let parseInt s = System.Int32.Parse(s)
let parseFloat s = System.Double.Parse(s)
let doSomething () =
let i = parseInt |> run4
let f = parseFloat |> run4
f |> ignore

// Make it more generic ->
//let doSomething2 (runner:(string->'a)->'b) =
let doSomething2 runner =
// Error on the following lines with both declarations
let i = parseInt |> runner
let f = parseFloat |> runner
f |> ignore

// Want to do something like
let test () =
doSomething2 run4
doSomething2 run5

// Workaround
let workaround (runner:IRunner) =
let run f = runner.Run f
let i = parseInt |> run
let f = parseFloat |> run
f |> ignore

有人可以对此有所启发吗?我没有找到任何相关问题,抱歉,如果我重复了一些内容。

最佳答案

问题是,如果 doSomething2 的类型是 ((string->'a) -> 'b) -> unit,那么 'a'b 在每次调用 doSomething2 期间都是固定的,这不是您想要的 - 在您的情况下 'a 需要处理intfloat单个 doSomething2 调用期间。

看起来你真正想要的更像是:doSomething2 : (forall 'a. (string -> 'a) -> 'a) -> unit,但是那种直接通用的F# 中不存在量化。正如您所发现的,解决此问题的方法是使用具有泛型方法的类型。

即使 F# 确实支持 forall 类型,正如我在评论推理中提到的那样,仍然不可能。考虑您的 doSomething2 函数 - 我们知道 runner 需要能够将类型为 string -> int 的输入转换为某种输出类型和string -> float 类型的输入到某些(可能不同的)输出类型。以下是 doSomething2 的几种不同签名,它们都满足此要求:

  1. forall 'a. 'a -> 'a
  2. forall 'a. (字符串 -> 'a) -> 'a
  3. forall 'a. 'a -> 单位

请注意,这些类型都不比其他类型更通用,它们都是不兼容的。在第一种情况下,我们可以将 id 传递给函数,在第二种情况下,我们可以将 run4 传递给它,在第三种情况下,我们可以将 忽略(但这些函数都不与其他可能的签名兼容!)。

关于f# - 可能的 F# 类型推断限制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11547804/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com