type Interpreter<'a> =
| RegularInterpreter of (int -> 'a)
| StringInterpreter of (string -> 'a)
let add<'a> (x: 'a) (y: 'a) (in_: Interpreter<'a>): 'a =
match in_ with
| RegularInterpreter r ->
x+y |> r
| StringInterpreter r ->
sprintf "(%s + %s)" x y |> r
无法解析的错误信息
'a
在编译时对我来说很清楚。我猜测是否可以使上述工作的问题的答案是否定的,没有直接将函数添加到数据类型中。但那我不妨使用一个接口(interface),或者完全摆脱泛型参数。编辑:马克的回复确实符合我的要求,但让我扩展这个问题,因为我没有充分解释它。我想要做的是用上面的技术做的是模仿在这个 post 中所做的事情。 .这样做的动机是避免内联函数,因为它们的可组合性很差——如果没有专门的通用参数,它们就不能作为 lambdas 传递。
我希望我可以通过将带有通用参数的联合类型传递给闭包来解决它,但是......
type Interpreter<'a> =
| RegularInterpreter of (int -> 'a)
| StringInterpreter of (string -> 'a)
let val_ x in_ =
match in_ with
| RegularInterpreter r -> r x
| StringInterpreter r -> r (string x)
let inline add x y in_ =
match in_ with
| RegularInterpreter r ->
x in_ + y in_ |> r
| StringInterpreter r ->
sprintf "(%A + %A)" (x in_) (y in_) |> r
let inline mult x y in_ =
match in_ with
| RegularInterpreter r ->
x in_ * y in_ |> r
| StringInterpreter r ->
sprintf "(%A * %A)" (x in_) (y in_) |> r
let inline r2 in_ = add (val_ 1) (val_ 3) in_
r2 (RegularInterpreter id)
r2 (StringInterpreter id) // Type error.
最后一行给出了一个类型错误。有没有解决的办法?尽管由于它们对可组合性的限制,我更希望函数不要被内联。
最佳答案
删除类型注释:
let inline add x y in_ =
match in_ with
| RegularInterpreter r ->
x + y |> r
| StringInterpreter r ->
sprintf "(%A + %A)" x y |> r
您还需要进行一些其他更改,我也在上面合并了这些更改:
sprintf
一起使用的格式说明符更通用的东西。当您使用 %s
,您是说该占位符的参数必须是字符串,因此编译器会推断出 x
和 y
成为 string
值(value)观。 inline
关键词。 通过这些更改,
add
的推断类型就是现在:x: ^a -> y: ^b -> in_:Interpreter<'c> -> 'c
when ( ^a or ^b) : (static member ( + ) : ^a * ^b -> int)
您会注意到它适用于
+
的任何类型。定义为将输入参数转换为 int
.在实践中,这可能只意味着 int
本身,除非您定义自定义运算符。FSI 烟雾测试:
> add 3 2 (RegularInterpreter id);;
val it : int = 5
> add 2 3 (StringInterpreter (fun _ -> 42));;
val it : int = 42
关于f# - 有没有办法让这种延续传递与 codata 示例在 F# 中工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41322308/