首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Monads和SML模块

Monads和SML模块
EN

Stack Overflow用户
提问于 2018-02-26 21:25:57
回答 1查看 550关注 0票数 2
代码语言:javascript
复制
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做事情的函数

代码语言:javascript
复制
fun mapToPair f x =
    let val b = List.fmap f x
    in (b,b)
    end

val lst = mapToPair incByFive [1,2,3];

假设您想要创建一个通用的实现,它适用于MAPPABLE的所有实例。以下代码不起作用

代码语言:javascript
复制
fun mapToPair f x =
    let val b = MAPPABLE.fmap f x
    in (b,b)
    end

似乎,如果需要这样做,SML人员会指出函数器。我尝试实现了一个,作为mapToPair的通用实现

代码语言:javascript
复制
functor FMAPFUNCTOR (structure Q : MAPPABLE)
 = struct
   fun mapToPair f x =
       let val b = Q.fmap f x
       in (b,b)
       end
end;

然而,为了使用它,在Haskell中我称之为函数器实例,我需要实例化函数器(这让我想起C++模板,出于某种原因)

代码语言:javascript
复制
structure MAPPABLE_TO_PAIR = FMAPFUNCTOR (structure Q = List);
val lstByPoly = MAPPABLE_TO_PAIR.mapToPair incByFive [1,2,3]

我将不得不为我想要使用的每个可映射实例重复该实例化。我猜Haskell也会执行类似的操作。只是隐含的。

现在我想知道在SML中是否有我错过的更好的“用户体验”的捷径/糖。因为实际上,为了在代码库中使用它,似乎有很多样板。

EN

回答 1

Stack Overflow用户

发布于 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

代码语言:javascript
复制
;; 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)的例子,它可以做一些与模块类似的通用操作。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48989663

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档