Scala中的异构列表;使用map函数

3
所以问题在于理解 shapeless 库的 HLists https://github.com/milessabin/shapeless ; 我正在使用 HLists 存储一些函数,例如:
val list = HList(
    function1(_),
    function2(_),
    ....
    functionn(_)
);

它很完美地工作:我可以从列表中选择任何函数并应用它:list.head(object)

但是,我在使用map函数(list map mapFunc)时遇到了问题:

object mapFunc extends Poly1 {
  implicit def default[T] =
    at[T](t => {
      t(obj)
    })
}

它说“应用程序不接受参数”。那么我该怎么处理呢?也许我没有理解某些东西?我是Scala新手。
附注:构造函数有一个有趣的效果,这段代码构建有点不正确: function1(_):: function2(_):: HNil 被识别为某种类型的函数,但HList(function1(_),function2(_))具有正确的类型。
编辑:
“p.s.”已经解决 - function1(_):: function2(_):: HNil 确实有类型不匹配的问题;但是function1 _ :: function2 _ :: HNil 没问题!
1个回答

4

首先回答你的最后一个问题——你需要以HNil作为列表的结尾,而不是HList。因此,例如我们有以下内容:

def function1(s: String) = "foo " + s
def function2(s: String) = s.toInt
def function3(s: String) = s + " bar"

我们需要写如下内容:
val list = function1 _ :: function2 _ :: function3 _ :: HNil

::像Scala标准库(和其他语言)中的cons运算符一样,它将第一个参数(项目)添加到第二个参数(列表)的前面。

现在是你的第一个问题。鉴于我刚定义的HList,我们可以编写以下内容:

val obj = "13"

object mapFunc extends Poly1 {
  implicit def funcTo[T] = at[String => T](f => f(obj))
}

然后:
scala> (list map mapFunc) == "foo 13" :: 13 :: "13 bar" :: HNil
res0: Boolean = true

关键是你需要表示当映射元素是从字符串(或者你的对象类型)到某个值的函数时,这种情况是适用的。

哦,抱歉,真的是HNil,我在提问时弄错了,已经修正了,谢谢! - DaunnC
嗯,是的,我明白了,这真的很令人兴奋;如果我想有许多不同的函数,从不同类型到另一种类型呢? 像 ~ def function1(s: Type1) = convertType1ToType2 ... def functionn(s: Typen-1) = convertTypen-1ToTypen ; 我的意思是,类似于 at[FromType => ToType];也许有一种方法可以不编写所有情况来应用隐式函数吗? - DaunnC
1
@DaunnC 如果你想将一个函数HList应用到一个参数HList上,那么你应该研究一下zipApply...但这是另一个问题。 - Miles Sabin
嗯,目的不是要完全应用,而是在使用map函数后将函数保留为它们本身(带有类型和应用可能性)。例如,我有另一个对象,并且我想在其中传递函数:implicit def funcTo[T] = at[T](t => someObject.hlist = t :: someObject.hlist) 然后应用此map函数后,我们将得到包含HList的someObjectsomeObject.hlist;但是,如果我们按照上面所写的那样做,我们无法从这个新的HList中应用函数:someObject.hlist.head(object)会给我们“Application doesnt take parameters”错误。 - DaunnC
我不明白为什么在创建函数的 HList 时省略括号会有影响;也许如果我们偏离了主题,有一个有用的参考资料会很有帮助? - bbarker
不确定在Scala中是否可行,但在Haskell中,您可以创建类型对齐的二叉树 https://hackage.haskell.org/package/type-aligned-0.9.6/docs/src/Data-TASequence-BinaryTree.html#BinaryTree它可以存储函数序列,使得第n个函数的输入是n-1个函数的输出,因此您可以拥有像这样的函数[a -> b、b -> c、c -> d],并且树的类型为BinaryTree (->) a d。 - Safareli

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接