将值列表应用为函数的参数

时间:2015-12-07 16:29:48

标签: elm

我可以将n个值的列表应用于带n个值的函数,其中n变化吗?

第一次天真的尝试如下,但编译器(公平地)抱怨weird self-referential type for applyN

applyN f xs =
    case xs of
        [] -> f
        (x::xs) -> applyN (f x) xs

我无法看到折叠如何工作并尊重其类型签名。

对于上下文,我想要一个N Json解码器列表并评估

Json.objectN ConstructorN n1 n2 ... nN

显然,如果n已知(让我们说2),那么我们有

case lst of
    (d1 :: d2 :: _) -> Json.object2 Constructor2 d1 d2
    otherwise -> ....

但如果我不能概括为n,那就要编写很多代码。

我担心它不可能像Haskell那样needs some special compiler flags

2 个答案:

答案 0 :(得分:1)

不,你不能这样做,至少不是没有依赖类型或至少是某种类型级别的欺骗,在Elm中没有(参考:How do I define Lisp’s apply in Haskell?

(这就是为什么顺便说一下所有objectN函数的原因。)

尝试重新构建代码 - 不能f只列出一个列表吗?

答案 1 :(得分:1)

在Json解码的上下文中,如果你有一个带解码器的列表文字,你可以做一些等同于applyN的事情。此模式使用map : (a -> b) -> Decoder a -> Decoder bandMap : Decoder (a -> b) -> Decoder a -> Decoder b函数。你这样使用它:

Constructor
  `Json.map` n1
  `Json.andMap` n2
  `Json.andMap` ...
  `Json.andMap` nN

可悲的是andMap并未为每个核心模块提供。如果有map2andThen,您可以自行定义。在这种情况下,object2有效,它与map2基本相同。所以:

andMap : Decoder (a -> b) -> Decoder a -> Decoder b
andMap decFun decA =
  object2 (\f a -> f a) decFun decA

您也可以使用Json.Decode.Extra.apply,这是同一件事,只是以非标准的方式命名*。

*无论如何,在榆树世界中都是非标准的