首先,回答您提出的字面问题。在列表推导中引用列表本身的方法是给它一个绑定。人为的例子:
a2z = 'a':[ succ (a2z!!i) | i <- [0..24]]
fibo = 0:1:[fibo !! i + fibo !! (i+1) | i <- [0..]]
现在,至于 pangram 程序。看起来好像您想要自己解决它的提示,而不是一个完整的解决方案,所以:您想要的不是将您的字符串与文字字母表进行比较,而是测试基于输入字符串的谓词是否适用于每个字符字母表。也就是说,您的谓词是输入的某些函数,对于字母表中的all 字符必须为真。你可以试着填补这个骨架上的洞:
import Data.Char (toLower)
main :: IO ()
main = interact ( unlines . map show . map isPangram . lines )
isPangram :: String -> Bool
isPangram xs = all (_ ys) alphabet
where alphabet = ['a'..'z']
ys = map toLower xs
正如 GHC 会告诉你的,缺失函数的类型是 :: String -> Char -> Bool。所以你也可以这样写:
import Data.Char (toLower)
main :: IO ()
main = interact ( unlines . map show . map isPangram . lines )
isPangram :: String -> Bool
isPangram xs = all p alphabet
where alphabet = ['a'..'z']
ys = map toLower xs
p :: Char -> Bool
p c = _
您可以删除ys 参数并直接在p 中引用ys,因为该变量保存规范化的输入,在p 的范围内。
也许您想对当前程序进行调整。在这种情况下,您生成的列表是Bool 的列表。如果列表包含字母表中的每个字母,则您可以使程序运行,True 如果该字母出现在输入中,False 如果没有。您还可以使用 all 将此列表缩减为单个布尔值。
如果您想要累积字符串中迄今为止遇到的所有字母的集合,并在它等于整个字母表时停止,您需要一个更复杂的递归尾递归函数。它将其累积参数构建为类似于插入Data.List.Ordered,确保仅插入字母表中的元素,每个元素仅插入一次,并在累积集的基数(即有序列表的length ) 与字母表相同。然而,从完整的字母表开始并在遇到元素时删除它们会更有效,当输入或字母表为空时停止:
import Data.Char (toLower)
import Data.List -- You’ll need a function from here.
main :: IO ()
main = interact ( unlines . map show . map isPangram . lines )
isPangram :: String -> Bool
isPangram xs = isPangram' alphabet ys
where alphabet = ['a'..'z']
ys = map toLower xs
isPangram' :: [Char] -> [Char] -> Bool
isPangram' [] _ = _ -- There are no more letters to search for.
isPangram' _ [] = _ -- There is nothing left to search.
isPangram' ws (z:zs) = isPangram' _ _ -- Remove an element from both lists.
另一种方法是将输入 filter 归一化所有无关元素,并将剩下的 nub 作为 Char 的列表。