Ale*_*lex 14 polymorphism monads ocaml existential-type state-monad
我试图在OCaml中实现状态monad(作为练习).我的实现看起来像这样:
module type MONAD_BUILDER =
sig
type 'a t
val return : 'a -> 'a t
val bind : 'a t -> ('a -> 'b t) -> 'b t
end;;
module MonadBuilder = functor (M: MONAD_BUILDER) ->
struct
let ( >>= ) = M.bind
let return = M.return
end;;
module StateM =
struct
type 'a state = { state: 's . 's -> ('a * 's) }
type 'a t = 'a state
let return x = { state = fun s -> (x, s) }
let bind m f =
let aux s =
let (x, s') = m.state s in
(f x).state s'
in { state = aux }
let run m x = fst (m.state x)
end;;
Run Code Online (Sandbox Code Playgroud)
我为记录字段选择了存在类型,因为我不喜欢使用仿函数并将状态类型包装在模块中.上述实施工作,但我遇到了一个问题,同时实施getState
和setState
.我尝试实现它们:
let getState = { state = fun s -> (s, s) }
let setState s = { state = fun _ -> ((), s) }
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为推断的字段类型(例如'a -> ('a * 'a)
和'a -> (unit * 'a)
)不如声明的类型通用's . 's -> ('a * 's)
.我理解为什么会发生这种情况,但我想知道是否有另一种方法可以使用记录方法使其工作?
谢谢.
干杯,亚历克斯
Vic*_*let 13
's. 's -> ('a * 's)
是一种通用类型.你将很难实现具有通用类型的状态......
在不使用模块的情况下,没有干净的方法来封装存在类型(因为存在类型是抽象类型的用途).
当然,您可以发布状态类型:
type ('a,'s) state = { state : 's -> ('a * 's) }
Run Code Online (Sandbox Code Playgroud)
甚至更短,
type ('a,'s) state = 's -> 'a * 's
Run Code Online (Sandbox Code Playgroud)
使用附加参数,您的代码将运行.但是,您遇到的事实是您的参数必须由monad处理.所以,你可以在构建monad时隐藏它:
module Monad = MonadBuilder(struct
include StateM
type 'a t = ('a,myStateType) state
end)
Run Code Online (Sandbox Code Playgroud)
或者改变你的monad设计,以包含一个用于存在类型的附加类型参数:
module type MONAD_BUILDER =
sig
type ('a,'param) t
val return : 'a -> ('a,'param) t
val bind : ('a,'param) t -> ('a -> ('b,'param) t) -> ('b,'param) t
end;;
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1841 次 |
最近记录: |