【问题标题】:Feed elements of a tuple to a function as arguments in Haskell?将元组的元素作为Haskell中的参数提供给函数?
【发布时间】:2011-07-04 07:52:23
【问题描述】:

在我的 Haskell 程序中,我想使用 printf 来格式化一个元组列表。我可以将 printf 映射到一个列表上,以一次打印出一个值,如下所示:

mapM_ (printf "Value: %d\n") [1,2,3,4]

Value: 1
Value: 2
Value: 3
Value: 4

我希望能够做这样的事情:

mapM_ (printf "Values: %d %d\n") [(1,100),(2,350),(3,600),(4,200)]

Values: 1 100
Values: 2 350
Values: 3 600
Values: 4 200

但这会将一个元组传递给 printf,而不是两个单独的值。如何将元组转换为 printf 的两个参数?

【问题讨论】:

标签: haskell functional-programming printf currying


【解决方案1】:

Text.Printf 的类型安全替代方案是 formatting 包。 Text.Printf.printf 不确保在编译时格式化参数的数量与参数的数量及其类型一致。阅读 Chris Done 的文章,What's wrong with printf? 以获取示例。

示例用法:

{-# LANGUAGE OverloadedStrings #-}
import Formatting

map (uncurry $ formatToString ("Value: " % int % " " % int)) [(1,100), (2,350), ...]
map (\(x,y) -> formatToString ("Value: " % int % " " % int) x y) [(1,100), (2,350), ...]

它需要 GHC 扩展 OverloadedStrings 才能正常运行。

虽然formatToString ("Value: " % int % " " % int) 具有Int -> Int -> String 类型,但取消curry 会给出(Int, Int) -> String 类型,其输入类型与列表中的元素匹配。

重写过程可以分解;假设f = formatString ("Value: " ...)

map (\(x,y) -> f x y)  ≡  map (\(x,y) -> uncurry f (x,y))  ≡  map (uncurry f)

也就是说,首先你 uncurry f 来实现接受元组的函数,然后你执行一个常规的Eta-conversion,因为\(x,y) -> uncurry f (x,y) 等同于简单的uncurry f。要打印结果中的每一行,请使用mapM_

mapM_ (putStrLn . uncurry $ formatToString ...) [(1,100), (2,350), ...]

如果您运行 hlint YourFile.hs,则会向您推荐这些重写。

【讨论】:

    【解决方案2】:
    mapM_ (\(x,y) -> printf "Value: %d %d\n" x y) [(1,100),(2,350),(3,600),(4,200)]
    

    【讨论】:

      【解决方案3】:

      函数uncurry 将一个有两个参数(咖喱)的函数转换为一个成对的函数。这是它的类型签名:

      uncurry :: (a -> b -> c) -> (a, b) -> c
      

      你需要在printf上使用它,像这样:

      mapM_ (uncurry $ printf "Values: %d %d\n") [(1,100),(2,350),(3,600),(4,200)]
      

      另一种解决方案是使用模式匹配来解构元组,如下所示:

      mapM_ (\(a,b) -> printf "Values: %d %d\n" a b) [(1,100),(2,350),(3,600),(4,200)]
      

      【讨论】:

        猜你喜欢
        • 2012-05-24
        • 2015-01-05
        • 2012-02-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-01
        • 1970-01-01
        相关资源
        最近更新 更多