【问题标题】:Elm calculation using fold使用折叠的榆树计算
【发布时间】:2020-06-25 03:37:45
【问题描述】:

我刚开始玩 Elmfunctional programming。我真的很喜欢这种语言,但我在实现非常简单的计算时遇到了麻烦。

我下面的代码将wacc : Floatcfs : List Float 作为输入,并且应该计算一个净预设值(即,为cfs 的每个元素计算cfs_i / (1 + wacc)^i,然后计算这些值的总和)。

代码有效,但非常冗长,可能不习惯。

我的主要问题除了提示如何使其更简洁/惯用之外是如何更改我的代码以能够接受 types Maybe 的 wacc 和 cfs。

对任何提示/信息都有帮助。谢谢!

-- helper functions
zip : List a -> List b -> List (a,b) 
zip list1 list2 =
    List.map2 Tuple.pair list1 list2

calcDF : Float -> Int -> List Float
calcDF wacc n = 
    let
        waccs = List.repeat n wacc
        time = List.range 0 n |> List.map toFloat
        waccs_time = zip waccs time
    in
        List.map (\x -> 1/ (1 + Tuple.first x)^(Tuple.second x)) waccs_time

-- my npv function
calcNPV : List Float -> Float -> Html text
calcNPV cfs wacc = 
    let 
        n = List.length cfs
        df = calcDF wacc n
        cfs_df = zip cfs df
    in
        List.map (\x -> (Tuple.first x) * (Tuple.second x)) cfs_df
        |> List.foldl (+) 0 

例子:

calcNPV [100,100,100] 0.1

-- returns 273.553719

【问题讨论】:

  • 您希望 cfs 参数是浮点数列表还是浮点数列表,即 Maybe (List Float)List (Maybe Float)?换句话说,您是在准备丢失整个列表还是丢失列表中的单个值?

标签: elm idioms


【解决方案1】:

我不确定你为什么要使用 Maybes。

但正如您所怀疑的那样,您使当前代码比需要的更复杂。这是对第一个功能的改造。你想要 n 个折扣值,所以我们首先创建一个包含 n 个项目的东西来循环,然后在 map 函数中进行计算

calcDF : Float -> Int -> List Float
calcDF wacc n =
    List.range 0 n
        |> List.map (calcDF_ wacc)
calcDF_ : Float -> Int -> Float
calcDF_ wacc idx =
    1 / (1 + toFloat idx) ^ wacc

如果您使用 https://package.elm-lang.org/packages/elm-community/list-extra/latest/List-Extra#indexedFoldl,您可以简化 main 函数,只需调用 calcDF_,同时循环折叠 cfs 并完全跳过 calcDF

【讨论】:

  • 感谢您的建议。是的,由于缺乏函数式编程经验(这就是我想首先学习它的原因),我把它弄得很复杂。在here 的帮助下,我想出了一个新的解决方案
【解决方案2】:

在 Elm 讨论论坛(参见 here)的帮助下,我想出了以下解决方案。

NPV 计算没有 type Maybe

calcNPV : List Float -> Float -> Float
calcNPV cashflows wacc = 
    let
        time = List.length cashflows |> List.range 0 |> List.map toFloat 
        waccs = List.repeat (List.length cashflows)  wacc

        calcPV : Float -> Float -> Float -> Float
        calcPV cf i t = cf / (1+i)^t
    in
        List.map3 calcPV cashflows waccs time |> List.foldl (+) 0

NPV 计算 type Maybe

calcMaybeNPV : List (Maybe Float) -> Maybe Float -> Maybe Float
calcMaybeNPV maybecashflows maybewacc = 
    let
        time = List.length maybecashflows |> List.range 0 |> List.map (\x -> Just (toFloat x))
        waccs = List.repeat (List.length maybecashflows)  maybewacc 

        calcPV : Maybe Float -> Maybe Float -> Maybe Float -> Maybe Float
        calcPV cf i t = 
            Maybe.map3 (\a b c -> a / (1+b)^c) cf i t
    in
        List.map3 calcPV maybecashflows waccs time |> List.foldl (Maybe.map2 (+)) (Just 0)

【讨论】:

    猜你喜欢
    • 2019-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-08
    • 1970-01-01
    • 2018-01-02
    • 2014-01-28
    相关资源
    最近更新 更多