我还在学习Haskell,而且我正在做一些练习,但是我还是一团糟。所以我有一个名为“novel”的函数,它需要2个字符串和一个Int
(novel :: (String, String, Int) -> String
)的论点。 Novel的输入/输出必须如下所示:
> novel ("Rowling", "Harry Potter", 1998)
"Harry Potter (Rowling, 1998)"
这是我的新颖功能的代码,如上所述:
novel :: (String, String, Int) -> String
novel (author, book, year) = book ++ " (" ++ author ++ ", " ++ (show year) ++ ")"
我正在尝试编写一个名为“cite”(cite :: [(String, String, Int)] -> String
)的新函数。 Cite的输入/输出应如下所示:
> cite [("author1", "book1", year1), ("author2", "book2", year2), ("author3", "book3", year3)]
"book1 (author1, year1)
book2 (author2, year2)
book3 (author3, year3)"
我试图以递归方式使用“小说”,以获得所需的输出,但我不知道该怎么做。
我尝试了什么:
cite :: [(String, String, Int)] -> String -- | Listed arguments
cite [] = "" -- | Base Case
cite x:xs = [(novel (author, book, year)), (novel (author, book, year)), (novel (author, book, year))]
老实说,就我而言。显然,它不起作用,但我不知道该怎么做。
答案 0 :(得分:5)
也许这会给你一个良好的开端:
cite :: [(String, String, Int)] -> String
cite [] = ""
cite (x:xs) = undefined -- put your code that recursively calls cite in here, hint: use ++ and "\n\"
模式匹配(x:xs)
说明了这一点,给我列表x
中的第一项和列表xs
的尾部。这与撰写本文相同:
cite xs' = let x = head xs'
xs = tail xs'
in undefined -- your code here
甚至
cite xs' = undefined -- your code here
where
x = head xs'
xs = tail xs'
希望这有助于推动你朝着正确的方向前进。
编辑:OP询问如何递归执行此操作,以下是我的原始答案:
您应该重新编写基本案例来说cite [] = ""
。它并没有真正有所作为,但它有助于提高代码的可读性。
让我们首先将“:t map novel”放入ghci,看看你得到了什么:
> :t map novel
map novel :: [([Char], [Char], Int)] -> [[Char]]
我们可以将其重写为:map novel :: [(String, String, Int)] -> [String]
如何?因为map
将一种类型a
转换为另一种类型b
,并将其应用于列表中的每个项目。 map
的第一个参数是任何带有一个参数的函数。正是novel
的作用。
但是这并没有给我们你需要的东西,我们最终会得到一个字符串列表而不是字符串:
> cite [("author1", "book1", year1), ("author2", "book2", year2), ("author3", "book3", year3)]
["book1 (author1, year1)","book2 (author2, year2)","book3 (author3, year3)"]
并且您希望它是由换行符“\ n”分隔的单个字符串。是否有一个函数可以获取字符串列表并将它们连接成一个字符串,但是在它们之间嵌入一个分隔符?
首先让我们描述一下这样一个函数:String -> [String] -> String
。接下来,我们将它放入Hoogle,看看我们得到了什么:https://www.haskell.org/hoogle/?hoogle=String+-%3E+%5BString%5D+-%3E+String
啊,第二个函数intercalate
听起来像我们需要的那样。它不仅适用于字符串,它适用于任何列表。它会如何工作?像这样:
> import Data.List (intercalate)
> intercalate "\n" ["List","Of","Strings"]
"List\nOf\nStrings"
所以现在你可以结合插入和地图来获得你想要的东西。我会将cite
的定义留给您。
[String] -> String
,则会找到unlines
答案 1 :(得分:1)
有一种相当简单的方法可以做到这一点。
首先,将novel
映射到给定列表的每个元素,然后使用Data.List.intersperse
填充换行符。这是我的实施:
import Data.List (intersperse)
cite :: [(String, String, Int)] -> String
cite bs = intersperse '\n' (map novel bs)
或者,以更优雅的无点风格:
cite = intersperse '\n' . map novel
还可以写一个漂亮,高效的递归函数:
cite [] = ""
cite [x] = novel x
cite (x:xs) = novel x ++ '\n' : cite xs
在未来的问题中,请记住map
和foldr
等函数 - 这些是Haskell和函数式编程中最重要的两个部分。此外,您的模式匹配需要括在括号中。