给出以下类型和成员函数
type Result<'TSuccess, 'TError> =
| Success of 'TSuccess
| Error of 'TError list
with
member this.apply fn =
match (fn, this) with
| Success(f), Success(x) -> Success(f x)
| Error(e), Success(_) -> Error(e)
| Success(_), Error(e) -> Error(e)
| Error(e1), Error(e2) -> Error(List.concat [e1;e2])
Run Code Online (Sandbox Code Playgroud)
以及内联函数
let inline (<*>) (f: ^A) (t:^A) =
let apply' = (^A : (member apply : ^A -> ^A) (t, f))
apply'
Run Code Online (Sandbox Code Playgroud)
而这个电话网站
let y () = Success (fun x -> x + 1) <*> (Success 3)
Run Code Online (Sandbox Code Playgroud)
我收到以下错误
let y () = Success (fun x -> x + 1) <*> (Success 3);;
-----------^^^^^^^^^^^^^^^^^^^^^^^^
/Users/robkuz/stdin(473,12): error FS0001: Type constraint mismatch.
The type
Result<'a,'c>
is not compatible with type
Result<('a -> 'b),'c>
The resulting type would be infinite when unifying ''a' and ''a -> 'b'
Run Code Online (Sandbox Code Playgroud)
这一切都是试图模仿Haskells Applicative并且签名应该是
(<*>) :: forall f a b. Apply f => f (a -> b) -> f a -> f b
Run Code Online (Sandbox Code Playgroud)
但我不认为在F#中无法表达这一点
有关如何实现这一目标的任何想法?
一般来说,我认为尝试在F#中模拟Haskell模式并不是一个好主意.在Haskell中,很多代码都是非常通用的,因为monad和applicatives的使用频率更高.
在F#中,我更喜欢编写更专业的代码,因为你不需要在monad或applicatives上编写代码多态,它只是让你更容易看到发生了什么.所以,我认为我不想<*>在F#中编写适用于任何"应用"的运算符.
也就是说,代码的问题在于<*>运算符^A对两个参数和结果使用相同的类型参数(虽然它们在调用中是不同的类型) - 如果使用三个单独的类型参数,它可以正常工作:
let inline (<*>) (f: ^B) (t:^A) : ^C =
let apply' = (^A : (member apply : ^B -> ^C) (t, f))
apply'
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
169 次 |
| 最近记录: |