如何重构这个Haskell函数链代码?


真不错
2025-03-12 03:57:04 (9天前)
  1. 任何Hasekll的方式呢?

在更一般的层面上:Haskell在这种情况下的表现如何(特别是考虑到它的不可变状态

特征
</跨度>
)?在这方面,它为开发人员提供了什么?或者说,Haskell本身没有扮演这个角色,而这只是一个困难的软件

工程
</跨度>
问题(没有未来的证据)我们必须跟上……

2 条回复
  1. 0# 不丶离 | 2019-08-31 10-32



    您可以做的一件事就是将这样的参数捆绑到一个参数对象中,正如bhelkir在评论中所建议的那样。如果向此对象添加新参数,则仍需要更改调用的客户端代码

    f1

    ,并改变该新参数的直接消费者(这里,

    f5

    ),但这些都是不可避免的:有人必须提供

    x

    在某些时候,你需要它作为客户;你必须消费

    x

    不知怎的,否则为什么要添加它开始?



    但是,你可以避免改变中间功能

    f1



    f2

    ,因为他们可以忽略他们不关心的新领域。你可以通过使用它来获得一些幻想

    Applicative

    实例

    ((->) t)

    (通常称为

    Reader

    传递此对象,而不是手动执行。这是写一个方法:




    1. module Test where
      import Control.Applicative

    2. data Settings = Settings {getA :: Int,
      getB :: Int,
      getC :: Int,
      getD :: Int}
      f1 :: Settings -> Int
      f1 = liftA2 (+) f2 f4
      f1 = do
      e1 <- f2
      e2 <- f4
      return $ e1 + e2

    3. f2 :: Settings -> Int
      probably something clever with liftA3 and (+) is possible here too
      f2 s = f5 s + getC s + f3 s

    4. f3 :: Settings -> Int
      f3 = liftA (* 2) getA

    5. f4 :: Settings -> Int
      f4 = liftA (+ 3) getD

    6. f5 :: Settings -> Int
      f5 = liftA (join ()) getB perhaps a bit opaque
      f5 = liftA square getB
      where square b = b
      b

    7. </code>


    现在,这有其优点和缺点:存在的逻辑

    f1

    (即知道你需要打电话

    f3



    a

    )已进入

    f3

    本身,这将发生在最初读取参数并在将其传递给某个辅助功能之前与其混淆的任何函数。这可能比原版更清晰,也可能掩盖背后的意图

    f1

    ,取决于您的问题域。您总是可以更明确地编写函数,例如通过修改传入函数

    Settings

    反对改变它的对象

    a

    传递它之前的字段,就像我做的那样

    f2

    举个例子。更一般地说,您可以使用最方便的样式编写任何函数:do-notation,applicative函数或传入的记录对象上的普通旧模式匹配。



    但最重要的是,添加一个新参数非常容易:你只需要添加一个字段

    Settings

    记录,并在需要它的函数中读取它:




    1. module Test where
      import Control.Applicative

    2. data Settings = Settings {getA :: Int,
      getB :: Int,
      getC :: Int,
      getD :: Int,
      getX :: Int}
      f1 :: Settings -> Int
      f1 = liftA2 (+) f2 f4
      f1 = do
      e1 <- f2
      e2 <- f4
      return $ e1 + e2

    3. f2 :: Settings -> Int
      probably something clever with liftA3 and (+) is possible here too
      f2 s = f5 s + getC s + f3 s

    4. f3 :: Settings -> Int
      f3 = liftA (* 2) getA

    5. f4 :: Settings -> Int
      f4 = liftA (+ 3) getD

    6. f5 :: Settings -> Int
      f5 = liftA2 squareAdd getB getX
      where squareAdd b x = b * b + x

    7. </code>


    请注意,除了之外,一切都是一样的

    data Settings



    f5



登录 后才能参与评论