我应该如何重构这个Haskell代码以使其更优雅?

时间:2011-04-01 21:02:25

标签: string haskell

作为练习,我写了一个简短的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评论的清洁卫兵。

4 个答案:

答案 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