我对Haskell库Control.Monad.Free中的函数hoistfree有一些疑问.给定f两个仿函数之间的转换,hoistfree f在相应的自由monad之间产生一个态射.这是它的定义.
hoistFree :: Functor g => (forall a. f a -> g a) -> Free f b -> Free g b
hoistFree _ (Pure a) = Pure a
hoistFree f (Free as) = Free (hoistFree f <$> f as)
Run Code Online (Sandbox Code Playgroud)
问题1如何哈斯克尔知道<$>被关联到地图上g,而不是f,Free f或Free g?
问题2为什么没有将hoistfree定义为
hoistFree :: Functor g => (forall a. f a -> g a) -> Free f b -> Free g b …Run Code Online (Sandbox Code Playgroud) 我试图在ocaml中编写一个免费的monad库,跟随haskell的Control.Monad.Free,但是我在一个点上,在hoistFree的实现中陷入困境.
hoistFree :: Functor g => (forall a. f a -> g a) -> Free f b -> Free g b
hoistFree _ (Pure a) = Pure a
hoistFree f (Free as) = Free (hoistFree f <$> f as)
Run Code Online (Sandbox Code Playgroud)
这是我翻译的尝试.
let rec hoistfree : 'b.('b t -> 'b t) -> 'a m -> 'a m =
fun f x -> match x with
| Return x -> Return x
| Free x -> Free (T.map (hoistfree f) (f …Run Code Online (Sandbox Code Playgroud) 我在lisp语言系列中接受了一些培训,现在我正在为自己的好处学习一些Haskell.在lisp中,功能样式是可以的,但有一些情况下必须使用命令式样式才能获得不错的性能,例如
附加
追加是缓慢的,因为它必须复制它的第一个参数(有时x100和成功摆脱它的版本一样慢).解决方法是将第一个列表的最后一个指针移动到第二个列表的开头,而不是附加.当然这是一种破坏性的操作.
分类
quicksort的功能版本创建了许多中间列表,这些列表以某种方式违背了算法的目的,即尽可能快.AFAIR,在常见的lisp中,sort是唯一没有功能版本的破坏性功能.
长度
这在lisp中是一项代价高昂的操作,因为必须在整个列表中查找其长度.这不一定是这样,afaik clojure以对数时间计算列表的长度.解决方案通常是在命令性循环中动态计算长度.
我的问题是,我们如何处理haskell中的这些问题?
是否有任何常见的lisp实现允许在运行时修改堆栈大小?堆的大小呢?
我正在使用sbcl,显然这些是在可执行文件启动时定义的,之后无法更改。
haskell ×3
common-lisp ×1
free-monad ×1
imperative ×1
lisp ×1
monads ×1
ocaml ×1
performance ×1