gpt4 book ai didi

haskell - printf 字符串列表

转载 作者:行者123 更新时间:2023-12-04 17:17:55 26 4
gpt4 key购买 nike

我有以下代码用于格式化电话号码。 (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" <operator> splitPlaces [3, 3, 4]

这样的运营商存在吗?它能存在吗?

最佳答案

假设这个运算符应该从列表中弹出元素并将它们一个一个地传递给一个函数,不,那不可能存在。不是真的。这当然不是一个好主意。为了使其正常工作,您需要在运行时决定传递函数的参数数量,完全规避类型系统及其所有好处。你可以说,列表正是在这里正确地陈述“我不知道会有多少元素。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

关于haskell - printf 字符串列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22520200/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com