如何在haskell中链接使用可能的参数?

mb1*_*b14 1 haskell

我正在尝试从可选参数构建一个字符串.例如,从标题和名称生成问候语字符串这在命令式语言中是微不足道的,看起来像这样

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}",但实际上,模板可以是发票,声明信,甚至是完整的会计报告.

Nik*_*kov 9

实际上Haskell比任何命令式方法更聪明.

让我们想象一下name它的价值Nothing.渲染类似的东西是否有意义"Hello Mr"?将它视为特殊情况可能会更有意义,为此我们可以再次使用它Maybe.首先,我将函数的签名更新为以下内容:

greeting :: Bool -> Maybe String -> Maybe String
Run Code Online (Sandbox Code Playgroud)

现在我们可以再次查看我们的问题,并发现Haskell提供了多种方法来处理它.

你好,Monads

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)

你好,Functors

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)

如果你发现这个语法更好.

  • "实际上,Haskell比任何必要的方法更聪明." 他说它是怎么回事!(尽管Haskell是最好的命令式语言.) (2认同)