我正在尝试从可选参数构建一个字符串.例如,从标题和名称生成问候语字符串这在命令式语言中是微不足道的,看起来像这样
def greeting(title, name):
s = "Hello"
if a :
s += "Mr"
if b:
s += b
Run Code Online (Sandbox Code Playgroud)
我在haskell的第一次尝试是:
greeting :: Bool-> Maybe String -> String
greeting title name = foldl (++) "Hello" (catMaybes [title' title, name])
where
title' True = Just "Mr"
title' False = Nothing
Run Code Online (Sandbox Code Playgroud)
我敢肯定有一种更好的方式来做到这一点.首先,我确信这种foldl catMaybes组合存在于某个地方,但我找不到它.其次,折叠在这里工作,因为我使用相同的操作(和相同的类型).那么有什么更好的方法呢?我也在考虑使用Writer,但我不确定如何做到这一点.
这只是一个例子(可能是坏的或太简单).我的问题更多,如何将其概括为许多论点.
所以真正的问题不只是关于连接2个字符串,而是更多如何使用可选的部分和参数从模板生成字母,就像在Word中使用邮件合并工具一样.
你有一个csv文件,其中包含客户名称,电话号码,逾期等等.某些字段可能是可选的.另一方面,您有一个模板,目标是根据*模板为每个客户(行)生成一个字母.那么问题是你如何在haskell中编写这个模板(没有任何模板库的帮助).在我的第一个例子中,模板将是"hello(Mr){name}",但实际上,模板可以是发票,声明信,甚至是完整的会计报告.
实际上Haskell比任何命令式方法更聪明.
让我们想象一下name它的价值Nothing.渲染类似的东西是否有意义"Hello Mr"?将它视为特殊情况可能会更有意义,为此我们可以再次使用它Maybe.首先,我将函数的签名更新为以下内容:
greeting :: Bool -> Maybe String -> Maybe String
Run Code Online (Sandbox Code Playgroud)
现在我们可以再次查看我们的问题,并发现Haskell提供了多种方法来处理它.
Maybe是一个monad,所以我们可以使用do它的语法:
greeting mr name = do
nameValue <- name
return $ if mr
then "Hello, Mr. " ++ nameValue
else "Hello, " ++ nameValue
Run Code Online (Sandbox Code Playgroud)
Maybe也是一个仿函数,所以我们可以使用fmap:
greeting mr name =
if mr
then fmap ("Hello, Mr. " ++) name
else fmap ("Hello, " ++) name
Run Code Online (Sandbox Code Playgroud)
如果我们将签名视为以下内容,我们也可以进行一些重构:
greeting :: Bool -> (Maybe String -> Maybe String)
Run Code Online (Sandbox Code Playgroud)
即,作为一个参数的函数,返回另一个函数.所以实现:
greeting mr =
if mr
then fmap ("Hello, Mr. " ++)
else fmap ("Hello, " ++)
Run Code Online (Sandbox Code Playgroud)
要么
greeting True = fmap ("Hello, Mr. " ++)
greeting False = fmap ("Hello " ++)
Run Code Online (Sandbox Code Playgroud)
如果你发现这个语法更好.