繁体   English   中英

在Haskell中以列表符号打印​​字符串

[英]Print a string in list notation in Haskell

我有一个函数,其中字符串被重复打印特定次数。 但是,如果给定一个负数,则该函数应打印出一个空列表。

main = print (repeat (-1) "Hello World")

repeat 1 x = x

repeat n x

  | n < 0 = *???*

  | n > 0 = x ++ repeat (n-1) x

我该怎么办,以便将空列表打印在方括号中而不是引号中?

repeat签名

repeat :: Int -> [a] -> [a]

我们希望n <= 0情况为“空”。 我们可以使用monoid:

import Data.Monoid

repeat :: Int -> [a] -> [a]
...
| n <= 0 = mempty

或写清单:

| n <= 0 = []

更新

如果我们希望为空字符串打印[] ,则必须“扩展” print功能,如下所示:

print' [] = putStrLn "[]"
print' z  = print z

目前尚不清楚您要做什么,因此问题出在哪里,所以这里有一些可能的解释。

  1. 您打算像现在一样构建一个字符串,但是希望将空字符串打印为'[]'而不是'“”'。

例如,考虑:let test = if(True)then [] else ['a']打印测试“”

如果这是问题,我不知道如何更改默认行为。 最好的方法是避免使用“打印”,而是结合使用“ putStrLn”和您自己的打印功能:

myShow :: String -> String
myShow "" = "[]"
myShow a = a

main = putStrLn . myShow $ (repeat (-1) "Hello World")
  1. 您实际上打算构建一个字符串列表,默认情况下为空字符串:

在这种情况下,您需要更改重复功能:

repeat 1 x = [x]
repeat n x 
  | n < 0 = []
  | n > 0 = x : repeat (n-1) x

现在,签名将repeat :: (Num a, Ord a) => a -> t -> [t] ,空情况将为[]。

您的问题实际上是使用Haskell的“无限”列表可以解决的一个难题。 这个想法是生成输入字符串的重新排列的无限列表,然后根据需要获取尽可能多的列表,然后决定如何打印该有限子列表:

printNTimes :: Int -> String -> IO ()
printNTimes n s = putStrLn . customShow . take n . repeat $ s
  where
    customShow [] = "[]"
    customShow ss = concat ss

标准的Prelude函数( repeat (与您自己定义的函数不同))采用某事物的一个示例,并通过简单地在“ forever”(一遍又一遍)上重复来创建此事物的无限列表。 所以:

repeat "hello" = ["hello", "hello", "hello", ...]   -- not valid Haskell
repeat 3 = [3, 3, 3, ...]   -- not valid Haskell

当然,我们永远无法在任何只有有限内存的机器上显示或以任何其他完全具体的方式实现无限列表。 但这不是问题,因为我们只需要列表的前n元素,这就是在上面的函数中take n要做的。 请注意,当n <= 0take n返回空列表,而不管其适用于什么,特别是take (-1) ["hello", "hello", ...] = []

一旦有了我们感兴趣的n元素,我们就可以按自己喜欢的方式显示它们,这就是customShow作用:如果看到一个空列表,则显示“ []”,否则它会连接我们所有的字符串只是从我们的重复列表中取出,并合并成一个长字符串,并以通常的方式显示出来。

在旁注中,在Haskell中最好的做法是分离纯函数,例如customShow . take n . repeat customShow . take n . repeat printNTimes IO操作(例如putStrLn customShow . take n . repeat printNTimes一部分。 printNTimes ,纯printNTimes和不纯printNTimes是根据成分组合在一起的,但是最好写一些类似...

showNTimes :: Int -> String -> String
showNTimes n = customShow . take n . repeat
  where
    customShow [] = "[]"
    customShow ss = concat ss

然后,也许在您的main功能中,您将得到一个类似这样的序列:

main :: IO ()
main = do
    s <- getLine
    ...
    putStrLn $ showNTimes 10 s
    ...

祝您拥有Haskelling好运! 这是一门美丽的语言,值得学习。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM