2011-04-01 12 views
6

Bir alıştırma olarak, bir dizenin ilk dört karakterini birleştirilmiş, kısa bir Haskell işlevi yazdım. Ben chars dizeleri dönüştürmek için büyük bir sorun vardı ve çirkin bir replicate hack başvurdu. Bu işlevi iyileştirmenin en iyi yolu nedir? (Ben desen ve çıkış hem geliştirilebilir olduğunu tahmin ediyorum.)Bu Haskell kodunu daha zarif hale getirmek için nasıl yeniden açmalıyım?

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." 

Güncelleme:, Herkese çok teşekkür ederim. Tüm cevaplardan ve yorumlardan birkaç şey öğrendim. Türleri daha iyi anlıyorum.

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

Güncelleme 2:

İşte kullanıyorum sona erdi kod ptival yorumuna başına xs _ ikinci desen değiştirildi. Tembel değerlendirme FTW.

Güncelleme 3: tew88'nin yorumcısından temizleyici muhafızları.

+4

concatFirstFour :: [a] -> [a] 'daha iyi – alternative

+1

Argümenin işlev gövdesinde hiçbir zaman kullanılmadığından, kodunuzun son satırında' xs 'adlarına gerek olmadığını unutmayın. Bunu wilcard '_' ile değiştirebilirsiniz. – Ptival

cevap

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

veya

concatFirstFour = take 4 

ama bu sonuncusu kısa listelerde başarısız değildir ...


Ayrıca türünü belirtmek gerek yok bir unutmayınız [ Char] (veya String), bu varsayımı asla kodda kullanmazsınız. Bırak a [a] -> [a].

4

Dizeler yalnızca karakter listeleridir, bu nedenle karakterleri dizeye dönüştürmeniz ve dizeleri birleştirmeniz gerekmez. Bunu yapmanın birkaç farklı yolu var.

Öncelikle, yalnızca bir öğeye sahip bir liste istiyorsanız, [x]'u kullanabilirsiniz. Bu nedenle, bu gerçekten gerekli değildir. Sadece yapabilirsiniz:

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

Ya da bu:

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

Ya benim tercih edilen yöntem: str yana

concatFirstFour str = take 4 str 

sadece bir liste, ilk dört karakterini take edebilirsiniz yeni bir "string" almak için

2

Ptival'ın desen eşleştirmesi ile çözümüne benzer. Ama bu, 4 karakterden az dizgilerle hata yapmıyor.

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

Sen bekçi ifadesinin bir parçası olarak 'aksi' anahtar kelimesini kullanmayı düşünebilirsiniz:

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

Bu desen eşleme seçtiğiniz yönteme göre biraz daha okunabilir (ve zarif) olduğunu düşünüyorum.

İlgili konular