signature MAPPABLE = sig
type 'a mappable
val fmap : ('a -> 'b) -> 'a mappable -> 'b mappable
end
structure Option : MAPPABLE = struct
type 'a mappable = 'a option
fun fmap f v =
case v of
(SOME x) => SOME (f x)
| NONE => NONE;
end
structure List : MAPPABLE = struct
type 'a mappable = 'a list
fun fmap f v = map f v
end
fun incByFive x = x + 5真的只是有一个用fmap做事情的函数
fun mapToPair f x =
let val b = List.fmap f x
in (b,b)
end
val lst = mapToPair incByFive [1,2,3];假设您想要创建一个通用的实现,它适用于MAPPABLE的所有实例。以下代码不起作用
fun mapToPair f x =
let val b = MAPPABLE.fmap f x
in (b,b)
end似乎,如果需要这样做,SML人员会指出函数器。我尝试实现了一个,作为mapToPair的通用实现
functor FMAPFUNCTOR (structure Q : MAPPABLE)
= struct
fun mapToPair f x =
let val b = Q.fmap f x
in (b,b)
end
end;然而,为了使用它,在Haskell中我称之为函数器实例,我需要实例化函数器(这让我想起C++模板,出于某种原因)
structure MAPPABLE_TO_PAIR = FMAPFUNCTOR (structure Q = List);
val lstByPoly = MAPPABLE_TO_PAIR.mapToPair incByFive [1,2,3]我将不得不为我想要使用的每个可映射实例重复该实例化。我猜Haskell也会执行类似的操作。只是隐含的。
现在我想知道在SML中是否有我错过的更好的“用户体验”的捷径/糖。因为实际上,为了在代码库中使用它,似乎有很多样板。
发布于 2018-02-27 00:41:43
我猜Haskell也是这样做的。只是隐含的。
Haskell标准库定义并导入了大量的类型类实例。给定一组足够的ML函数器、它们的应用程序以及它们隐式的编译时导入,您可以实现一些非常方便的操作。
但Haskell确实允许您以SML不能实现的方式自动执行类型类实例声明。
例如,instance Foo t => Bar t where ...可以与SML的高阶functor相媲美,但是在SML中,您必须显式地为每个具体的Foo t生成一个对应于Bar t的模块。Haskell还允许你在语法上使用derive instances。
OCaml从2014年就有了modular implicits (example),但它们主要是给你语法糖,让你引用定义的函数器实例,而不是生成它们。
我怀疑ML模块系统仍然比Haskell更明确的原因是因为像overlapping instances这样的东西。
Andreas Rossberg在2014年贡献了1ML,其中模块是一等公民。这意味着函数可以将模块作为参数,例如this
;; Higher-kinded polymorphism
type MONAD (m : type => type) =
{
return 'a : a -> m a;
bind 'a 'b : m a -> (a -> m b) -> m b;
};
map 'a 'b (m : type => type) (M : MONAD m) (f : a -> b) mx =
M.bind mx (fun x => M.return (f x));
do map :
'a => 'b => (m : type => type) => (M : MONAD m) => (a -> b) -> m a -> m b;这仍然是一种研究,因为编译器的名字中有“玩具”,但它将是一个ML (尽管不是标准ML)的例子,它可以做一些与模块类似的通用操作。
https://stackoverflow.com/questions/48989663
复制相似问题