当前位置:  开发笔记 > 小程序 > 正文

printf一个字符串列表

如何解决《printf一个字符串列表》经验,为你挑选了1个好方法。

我有以下代码可以格式化电话号码.(printf来自Text.Printf,splitPlaces来自Data.List.Split).

prettyPrint :: String -> String
prettyPrint phoneNumber = printf "(%s) %s-%s" part1 part2 part3
  where [part1, part2, part3] = splitPlaces [3, 3, 4] phoneNumber

我正在寻找的是一个允许以下方式编写函数的运算符:

prettyPrint = printf "(%s) %s-%s"  splitPlaces [3, 3, 4]

这样的运营商是否存在?它可以存在吗?



1> leftaroundab..:

假设此运算符应弹出列表中的元素并将它们逐个传递给函数,否则不能存在.不是真的.这当然不是一个好主意.为了使其正常工作,您需要在运行时决定传递函数的参数数量,完全规避类型系统及其所有好处.你可以说,列表正好在这里正确地陈述"我不知道会有多少元素.printf本身相当违反Haskell的哲学.它的类型类hackery的可变参数签名的原因并不是允许变化参数的数量,但不同类型的参数,在您的情况下不相关.

虽然容易实现的是从列表中获取固定数量的元素.再一次不是一个好主意,因为它必然是一个部分功能...但是这里有:

pop3 :: (a -> a -> a -> b) -> [a] -> b
pop3 f [x,y,z] = f x y z

允许你写

printf "(%s) %s-%s" `pop3` splitPlaces [3, 3, 4] phoneNumber

实际上,我们可以概括一下:在编译时仍然是固定数字,但是对于任何这样的数字都有一个名称:

{-# LANGUAGE MultiParamTypeClasses  #-}
{-# LANGUAGE FlexibleInstances      #-}

class YieldsEventually f a b where
  popN :: f -> [a] -> b

instance YieldsEventually b a b where
  popN = const

instance (YieldsEventually f a b) => YieldsEventually (a->f) a b where
  popN f (x:xs) = popN (f x) xs

但是,结合两个需要单态参数来解决自己的多态性 - 变量的函数不可能很好地工作,你需要完全限定一切以使其编译:

(printf "(%s) %s-%s" :: String -> String -> String -> IO())
         `popN` (splitPlaces [3, 3, 4] phoneNumber :: [String])

不好.

我认为你原来的方法是最好的; 显式模式还允许您插入适当的故障处理.


最后,显而易见的是,这里是动态数论证解决方案:

{-# LANGUAGE RankNTypes #-}

popNPrintfr :: PrintfArg a => (forall p. PrintfType p => p) -> [a] -> IO ()
popNPrintfr printr [] = printr
popNPrintfr printr (x:xs) = popNPrintfr (printr x) xs

再次使用起来更简单:

printf "(%s) %s-%s" `popNPrintfr` splitPlaces [3, 3, 4] phoneNumber

推荐阅读
吻过彩虹的脸_378
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有