首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如果函数可以是另一种类型,那么如何应用一元规则?

如果函数可以是另一种类型,那么如何应用一元规则?
EN

Stack Overflow用户
提问于 2018-09-16 04:31:59
回答 2查看 343关注 0票数 7

我正在考虑在clojure和scala之间进行一些互操作。由于java本身现在有lambdas,我在考虑数据之间的泛化以及如何将函数应用于集合。

  • 构造函数扩展了clojure.lang.IFn和generalises在clojure.lang.ISeq上的集合操作
  • scala函数扩展了scala.Functionscala.collection.Traversable上的集合操作。
  • java扩展了java.util.function.Function,并在java.util.stream.Stream上扩展了集合操作。

问题:

  • 在这种情况下,monads会有用吗?
  • 如果是这样的话,会在所有集合类型中实现map操作吗?

示例:

代码语言:javascript
复制
  (map (scala-fn +) 
       [1 2 3]
       (scala-seq [1 2 3]) 
       (.stream [1 2 3]))
  => (scala-seq [3 6 9])

继续(添加了haskell作为标签,以防人们可能知道核心类型)。

Clojure、Scala和Java中都有一些操作,它们接受集合,向集合应用函数并返回新集合。

  • 所有这些语言都运行在JVM上。
  • 但是,每种语言都定义自己的类来表示函数。

我对clojure比较熟悉,所以有些操作如下:

代码语言:javascript
复制
 (into {} [[:a 1] [:b 2]]) => {:a 1 :b 2}

它将clojure向量转换为clojure映射。因为into操作是在java.util.List上通用的,所以可以使用继承java.util.List的任何数据结构。

我希望与clojure中的scala库一起工作,并面对某些障碍:

  • Scala,像clojure一样,也具有不可变的数据结构,但是它们的定义与clojure数据结构非常不同。
  • Scala函数继承自scala.Function,因此需要包装到clojure.lang.IFn
  • Scala数据结构不从java.util.List继承,这意味着: (into {} (scala-list [:a 1] [:b 2]))将无法工作。
  • 我希望重新实现一些基本的clojure函数,这些函数也包含scala数据结构。(地图、缩小图、地图等)

该功能看起来类似于:

代码语言:javascript
复制
 (into {} (scala-list [:a 1] [:b 2])) => {:a 1 :b 2}

 (into (scala-map) [[:a 1] [:b 2]]) => (scala-map :a 1 :b 2)

 (concat (scala-list 1 2) [3 4]) => (scala-list 1 2 3 4)

 (concat [1 2] (scala-list 3 4)) => (1 2 3 4) ;lazy seq

 (map + [1 2] (scala-list 3 4)) => [4 6]

 (map (scala-fn +) [1 2] (scala-list 3 4)) => [4 6]
  • 我要寻找的是在集合操作中同时使用clojure和scala函数的能力。
  • 我可以在不使用monads的情况下做到这一点(通过检查集合和函数类型,并在函数应用程序之前进行一些胁迫)
  • 我在这里问的问题对我来说有点好奇,因为我所读到的关于单子的所有文献似乎都认为任何函数f:X->Y都是通用的。
  • 但是,在clojure/ scala /lambda互操作中,clojure函数、scala函数和java lambda并不是通用的。我很好奇如何用范畴理论来解决这个问题。
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-09-24 16:13:39

我只能给你Haskell的答案,因为我不会说任何其他语言。然而,在我看来,您似乎主要是在寻找一种将输入自动转换为函数的方法。这似乎与单曲没有任何关系。

代码语言:javascript
复制
(concat (scala-list 1 2) [3 4]) => (scala-list 1 2 3 4)

如果我把这个翻译成Haskell,我会给它这样的类型

代码语言:javascript
复制
concat :: (IsList l1, IsList l2) => l1 elem -> l2 elem -> [elem]

其中ToList是一个类型类型,它将把这个容器转换成一个列表。

代码语言:javascript
复制
class IsListOf a where
    toList :: a elem -> [elem]

从您的示例中还不清楚如何决定输出类型,因此我无法帮助您。

代码语言:javascript
复制
(map + [1 2] (scala-list 3 4)) => [4 6]

在Haskell中,这个函数不是map,而是zipWith。如果您想自动转换输入,可以这样做。

代码语言:javascript
复制
zipWith :: (IsList l1, IsList l2) => (a -> b -> c) -> l1 a -> l2 b -> [c]

如果您想要自动转换函数,您也可以这样做。

代码语言:javascript
复制
zipWith :: (IsList l1, IsList l2, Is2Function f) => f a b c -> l1 a -> l2 b -> [c]

Is2Function将再次成为一个只转换为2元函数的类型化类型。

代码语言:javascript
复制
class Is2Function f where
    toFunction :: f a b c -> a -> b -> c

关于泛化,也有一些需要记住的东西。我在前面说过,我不知道你将如何决定输出。这是编译器经常遇到的问题(至少在haskell中是这样)。概括从表面上看似乎不错,但它们并不总是使事情变得更清楚,并可能导致歧义。

票数 1
EN

Stack Overflow用户

发布于 2018-09-24 18:17:40

scala函数扩展了scala.Function和scala.collection.Traversable上的集合操作。 java扩展了java.util.function.Function,并在java.util.stream.Stream上扩展了集合操作。

首先,好消息是:这是不正确的,Java和Scala可以实现任何SAM (单一抽象方法)接口。这允许将Java与预期scala.FunctionN的API一起使用,而Scala使用期望java.util.function.*的API(包括Java )。这种互操作性应该在Scala2.12及更高版本中完成(据我所知)。

坏消息(您知道这即将到来):当具体谈到Scala集合API时,它也非常依赖于隐式参数,而这些参数在Java或Clojure中并不真正可用。类似地,Clojure集合API依赖于动态类型,而IFn不是SAM类型(因为它涵盖了具有不同数量的参数的函数)。当然,对于Clojure中的使用,Java和Scala之间的互操作没有帮助。

更普遍地说,3个集合API(如果算上Scala2.13中的重设计)可能太不同了,不可能像那样统一。

在这里,我看不出单子本身有什么用处。如果我试图从Clojure中执行一些有用的操作,我会使用“检查集合和函数类型,并在函数应用程序之前进行一些胁迫”作为解决方案。协议可以简化它,但需要一些性能成本。

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

https://stackoverflow.com/questions/52350969

复制
相关文章

相似问题

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