作为练习,我写了一个简短的Haskell函数,它返回一个字符串的前四个字符,连接起来。我很难将字符转换为字符串,并使用了一个丑陋的replicate
黑客。改善此功能的最佳方法是什么? (我猜测模式和输出都可以改进。)
concatFirstFour :: [Char] -> [Char]
concatFirstFour (a:b:c:d:_) = (replicate 1 a) ++ (replicate 1 b) ++ (replicate 1 c) ++ (replicate 1 d)
concatFirstFour xs = error "Need at least four characters."
更新:非常感谢大家。我从所有的答案和评论中学到了很多东西。我更了解类型。
以下是我最终使用的代码:
initFirstFour :: [a] -> [a]
initFirstFour str
| length str > 3 = take 4 str
| otherwise = error "Need at least four characters."
更新2:将第二个模式从xs更改为_每个ptival的注释。 Lazy eval FTW。
更新3:来自tew88评论的清洁卫兵。
答案 0 :(得分:10)
concatFirstFour (a:b:c:d:_) = [a,b,c,d]
concatFirstFour _ = error "Need at least four characters."
或
concatFirstFour = take 4
但最后一个在短名单上没有失败......
另请注意,您不需要指定类型是[Char](或String),因为您从不在代码中使用此假设。让它成为[a] - > [A]。
答案 1 :(得分:4)
字符串只是字符列表,因此您不需要将字符转换为字符串,然后连接字符串。有几种不同的方法可以做到这一点。
首先,如果您想要一个只包含一个元素的列表,可以使用[x]
。所以:
concatFirstFour (a:b:c:d:_) = [a] ++ [b] ++ [c] ++ [d]
但这不是必要的。你可以这样做:
concatFirstFour (a:b:c:d:_) = [a, b, c, d]
或者这个:
concatFirstFour (a:b:c:d:_) = a:b:c:d:[]
或者,我的首选方式:
concatFirstFour str = take 4 str
由于str
只是一个列表,因此您可以take
前四个字符来获取新的“字符串”。
答案 2 :(得分:4)
您可以考虑使用'otherwise'关键字作为保护表达式的一部分:
initFirstFour :: [a] -> [a]
initFirstFour xs
| length xs > 3 = take 4 xs
| otherwise = error "Need at least four characters."
我认为这比您选择的模式匹配方法更具可读性(和优雅性)。
答案 3 :(得分:2)
类似于Ptival使用模式匹配的解决方案。但是对于少于4个字符的字符串,这个不会出错。
concatFirstFour (a:b:c:d:_) = [a,b,c,d]
concatFirstFour xs = xs