试图让 State 和 Delayed monad 的结合工作
Trying to get bind working for combination of State and Delayed monad
如果这个问题的答案是"you are going about it all wrong",一定要告诉我一个更合适的方法。我的代码结构如下:
type Res<'T> =
| E of (DC -> 'T)
| V of 'T
现在这个类型主要是直接使用的,有很多内联代码手动绑定每个案例,这是我试图摆脱的很多样板,所以我想我把它变成一个计算表达。 map、bind 和 apply 并不难。
状态是通过 DC 进行的,但这很难正确,所以我将其更改为以下内容,这是我在与状态 monad 的讨论中看到的常见签名。
type Res<'T> =
| E of (DC -> DC * 'T)
| V of 'T
然后我决定将它提升到一个新的水平并引入 Delayed monad(或 Eventually 或任何它的名字)。所以我按如下方式更改了我的类型,使其递归:
type Res<'T> =
| E of (DC -> DC * Res<'T>)
| V of 'T
我尝试了以下的一些变体,但不断得到:
The resulting type would be infinite when unifying ''a' and 'Res<'a> -> Res<'b>'
(通常在我不调用 return 时发生,即下面的 Res.E <|
)
或者我似乎无法正确设置我的类型,以下(可以理解)会引发类型错误,但我在修复它时遇到了盲点:
This expression was expected to have type 'Res<'a>' but here has type 'DC * Res<'a>'.
let rec bind k res =
match res with
| Res.V v -> k v // not delayed, should it be?
| Res.E e ->
Res.E <| fun dc -> bind k (e dc) // here's my error, on 'e dc'
//(fun dc -> dc, bind f (e dc))
bind k res
我理解签名应该是('a -> Res<'b>) -> Res<'a> -> XRes<'b>
。问题来自正确的递归,至少在我的脑海中。我什至不确定为什么要将结果提供给 Res.E
,据我所知,k
continuation 应该已经 return 这种类型了。
此外,我目前有 return 如下(在 Steve Horsfield 之后):
let result v = Res.V v
但在一些帖子中也注意到了(特别是 hilarious Frankenfunctor):
let result v = Res.E <| fun dc -> dc, Res.V v
也许我正在遵循一种我不应该遵循的模式,但当时这似乎是个好主意,尤其是在尝试重构无数样板代码并将其替换为计算表达式时,但也许我应该坚持直接评价,很符合我的想法 ;).
但我觉得我很接近...有什么想法吗?
我不太确定这个 monad 的含义是什么,但是
好的,在稍微考虑一下并阅读问题的 header :- ) 之后,我 do 理解它的意思,并且我可以看到如何构建 bind
为此。
你的错误是包裹在 Res.E
中的函数应该 return 一个元组,但是你 return 只是 Res<'b>
通过递归调用 [=11] =].为了反映这一点,您将 e
的结果传递给递归 bind
调用以代替 Res<'b>
参数,而 e
实际上 return 是一个元组。
要正确执行此操作,您需要解构 e
的结果,然后将第二部分传递给递归 bind
调用,并将其结果与第一部分配对:
let rec bind (k: 'a -> 'b Res) (res: 'a Res) : 'b Res =
match res with
| V a -> k a
| E e ->
E <| fun dc ->
let dc', res' = e dc
dc', bind k res'
终结案,我想应该不会也拖延吧。也就是说,我没有看到它的原因。据我了解,V x
案例的解释应该是“a computation that doesn't change state and returns x
” ,在这种情况下,使其延迟不会增加任何内容,只会增加额外的 lambda-expression.
如果这个问题的答案是"you are going about it all wrong",一定要告诉我一个更合适的方法。我的代码结构如下:
type Res<'T> =
| E of (DC -> 'T)
| V of 'T
现在这个类型主要是直接使用的,有很多内联代码手动绑定每个案例,这是我试图摆脱的很多样板,所以我想我把它变成一个计算表达。 map、bind 和 apply 并不难。
状态是通过 DC 进行的,但这很难正确,所以我将其更改为以下内容,这是我在与状态 monad 的讨论中看到的常见签名。
type Res<'T> =
| E of (DC -> DC * 'T)
| V of 'T
然后我决定将它提升到一个新的水平并引入 Delayed monad(或 Eventually 或任何它的名字)。所以我按如下方式更改了我的类型,使其递归:
type Res<'T> =
| E of (DC -> DC * Res<'T>)
| V of 'T
我尝试了以下的一些变体,但不断得到:
The resulting type would be infinite when unifying ''a' and 'Res<'a> -> Res<'b>'
(通常在我不调用 return 时发生,即下面的 Res.E <|
)
或者我似乎无法正确设置我的类型,以下(可以理解)会引发类型错误,但我在修复它时遇到了盲点:
This expression was expected to have type 'Res<'a>' but here has type 'DC * Res<'a>'.
let rec bind k res =
match res with
| Res.V v -> k v // not delayed, should it be?
| Res.E e ->
Res.E <| fun dc -> bind k (e dc) // here's my error, on 'e dc'
//(fun dc -> dc, bind f (e dc))
bind k res
我理解签名应该是('a -> Res<'b>) -> Res<'a> -> XRes<'b>
。问题来自正确的递归,至少在我的脑海中。我什至不确定为什么要将结果提供给 Res.E
,据我所知,k
continuation 应该已经 return 这种类型了。
此外,我目前有 return 如下(在 Steve Horsfield 之后):
let result v = Res.V v
但在一些帖子中也注意到了(特别是 hilarious Frankenfunctor):
let result v = Res.E <| fun dc -> dc, Res.V v
也许我正在遵循一种我不应该遵循的模式,但当时这似乎是个好主意,尤其是在尝试重构无数样板代码并将其替换为计算表达式时,但也许我应该坚持直接评价,很符合我的想法 ;).
但我觉得我很接近...有什么想法吗?
我不太确定这个 monad 的含义是什么,但是
好的,在稍微考虑一下并阅读问题的 header :- ) 之后,我 do 理解它的意思,并且我可以看到如何构建 bind
为此。
你的错误是包裹在 Res.E
中的函数应该 return 一个元组,但是你 return 只是 Res<'b>
通过递归调用 [=11] =].为了反映这一点,您将 e
的结果传递给递归 bind
调用以代替 Res<'b>
参数,而 e
实际上 return 是一个元组。
要正确执行此操作,您需要解构 e
的结果,然后将第二部分传递给递归 bind
调用,并将其结果与第一部分配对:
let rec bind (k: 'a -> 'b Res) (res: 'a Res) : 'b Res =
match res with
| V a -> k a
| E e ->
E <| fun dc ->
let dc', res' = e dc
dc', bind k res'
终结案,我想应该不会也拖延吧。也就是说,我没有看到它的原因。据我了解,V x
案例的解释应该是“a computation that doesn't change state and returns x
” ,在这种情况下,使其延迟不会增加任何内容,只会增加额外的 lambda-expression.