2011-04-01 70 views
6

作爲練習,我編寫了一個簡短的Haskell函數,它返回串聯的前四個字符。我很難將字符轉換爲字符串,並使用了一個醜陋的replicate黑客。改進此功能的最佳方法是什麼? (我猜,這兩個模式和輸出得以提高。)我應該如何重構這個Haskell代碼以使它更優雅?

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的評論改變了第二圖案。懶惰eval FTW。

更新3:來自tew88的評論的清潔衛士。

+4

'concatFirstFour :: [a] - > [a]'更好 – alternative 2011-04-01 21:09:13

+1

請注意,您不需要在代碼的最後一行命名'xs',因爲參數在函數體中從不使用。你可以用wilcard'_'替換它 – Ptival 2011-04-01 23:58:28

回答

10
concatFirstFour (a:b:c:d:_) = [a,b,c,d] 
concatFirstFour _   = error "Need at least four characters." 

concatFirstFour = take 4 

但短名單中這最後一個不會失敗...


還要注意你不需要指定類型爲[ Char](或String),因爲你從不在代碼中使用這個假設。讓它成爲[a] - > [a]。

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

與使用模式匹配的Ptival解決方案類似。但是這個不會出現字符串小於4個字符的錯誤。

concatFirstFour (a:b:c:d:_) = [a,b,c,d] 
concatFirstFour xs  = xs 
4

您可以考慮使用「否則」關鍵字爲你守衛表達式的一部分:

initFirstFour :: [a] -> [a] 
initFirstFour xs 
    | length xs > 3 = take 4 xs 
    | otherwise  = error "Need at least four characters." 

我覺得這是一個有點比模式匹配您選擇的方法更具有可讀性(優雅)。