【问题标题】:Does idiomatic Haskell try to eliminate pair operations fst and snd, as it does head,init,tail etc?惯用的 Haskell 是否尝试消除对操作 fst 和 snd,就像它做 head、init、tail 等一样?
【发布时间】:2023-03-06 18:25:02
【问题描述】:

这是一个不适合我的功能,我想我需要摆脱 fst。

flagHolidays :: [(C.Day,Availability)] -> Handler [(C.Day,Availability)]
flagHolidays dayPairs = do
   let days = map fst dayPairs
       yepNope = Prelude.map isHoliday days
       availability = Prelude.map flagAvailability yepNope
   return $ Prelude.zip days availability

我能想到的唯一方法是一个非常丑陋的模式匹配,类似于(x,y):(xs,ys)。删除fst 有意义吗?如果是这样,模式匹配此对列表的最佳方法是什么?

【问题讨论】:

  • dayPars 的类型为 [(C.Day, Availability)]。你不能打电话给fst。您是否粘贴了正确的代码?
  • 无关:这是一个纯函数。没有必要将它放在 Handler monad 中。正如您所看到的in your other question,在单子中不必要地运行这样的函数只会使它们难以测试。您应该将其定义为纯函数并在必要时将其提升。

标签: haskell


【解决方案1】:

headtailinit 未在惯用的 haskell 代码中使用的原因是它们不是全部函数 - 某些输入会导致错误发生。将空列表传递给任何这些函数都会导致空列表异常。

fstsnd 没有这个问题,因为没有输入可以传递给那些会导致异常的函数。因此,没有理由尝试避免这些功能。

您的函数可以写得更好(其他 cmets 对此提供了很好的详细信息),但这不是因为使用了 fstsnd

【讨论】:

    【解决方案2】:

    使函数纯和

    flagHolidays = map (second $ flagAvailability . isHoliday)
    

    为了回答实际问题,除非作为参数传递,否则 fst 和 snd 很少使用。

    [编辑] 嗯,我写的有点仓促。这是错的。您正在传递一个对列表,并且从不使用该对的第二个组件。已更正,但本意相同(现在使用fst):

    flagHolidays = map ((id &&& flagAvailability . isHoliday) . fst)
    

    【讨论】:

    • fstsnd 有时对于编写处理元组的无点代码很有用。
    【解决方案3】:

    dayPairs 是对的列表,所以days 应该是map fst dayPairs。这就是使用fst 是惯用的一个地方,作为高阶函数的参数。除此之外,它主要用于当作者忘记惰性模式时延迟对对的评估。

    【讨论】:

      【解决方案4】:

      我认为你是对的,因为你这样做的方式似乎不是特别地道。

      除了错误,还有很多更好的方法。作为几个示例(可能不是最佳的,但仍然更易读),您可以在地图中使用 lambda:

      return $ map (\(d,a) -> (d, flagAvailability $ isHoliday a)) dayPairs
      

      或者您可以使用列表推导:

      return [(day, flagAvailability $ isHoliday a) | (day,a) <- dayPairs]
      

      可能有一些聪明的方法可以使中心映射完全无点,但即使这样也可能不值得——上述任何一种表达方式都使操作相当清晰。但是,我认为消除变量dayPairs 可能是一种改进:

      flagHolidays = return . map (\(d,a) -> (d, flagAvailability $ isHoliday a))
      

      【讨论】:

      • 不要忘记来自Control.Arrow的精彩组合子:return $ map (second (flagAvailability . isHoliday)) dayPairs
      猜你喜欢
      • 2016-10-30
      • 1970-01-01
      • 1970-01-01
      • 2023-03-10
      • 2021-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-27
      相关资源
      最近更新 更多