2012-11-10 23 views
2

我試圖做一個非常短的代碼,因爲我們有一個有利於最短代碼的reglementation。 我們必須創建一個函數,以相同的順序將列表變成一個新的升序和降序列表:例如。 [1,6,2,1,7,3,2,8,4],成爲[[1,6],[2,1],[7],[3,2],[8],[4]]壓痕的位置不正確?短代碼

所以我試圖做到以下幾點:

func :: Ord a => [a] -> [[a]] 
func xs = f1 d [a] 
f1 [] ys = [c] 
f1 xs ys | a >= b = d `f1` a:ys 
      | otherwise = c: d `f2` [a] 
f2 [] ys = [c] 
f2 xs ys | a < b = d `f2` a:ys 
      | otherwise = c : d `f1` [a] 
    where a = head xs 
      b = head ys 
      c = reverse ys 
      d = tail xs 

但我對line "b = head ys"得到

parse error on input '=' 

我認爲可以在where塊中定義多個函數嗎?

產生的誤差像很多

not in scope 'a' 
not in scope 'b' 
not in scope 'c' 
not in scope 'd' 

parse error on input 'b' 

其他壓痕我不得不做出這種方式節省一些代幣/較短的代碼。

+4

製表符?如果是的話,用火殺死他們。 –

+0

誰問過你這麼短的代碼,爲什麼? – AndrewC

回答

0

您的錯誤消息是因爲您混合了製表符和空格。最好只使用空格。

現在,如果你正在寫

a = head xs 
b = head ys 
c = reverse ys 
d = tail xs 

然後

xs = (a:ds) 
ys = (b:es) 

我們重寫代碼與模式匹配你的函數:

func :: Ord a => [a] -> [[a]] 
func [] = [] 
func (a:ds) = f1 ds [a] 
f1 [] ys = [reverse ys] 
f1 (a:ds) (b:es) | a >= b = ds `f1` (a:b:es) 
       | otherwise = reverse (b:es): ds `f2` [a] 
f2 [] ys = [reverse ys] 
f2 (a:ds) (b:es) | a < b = ds `f2` (a:b:es) 
       | otherwise = reverse (b:es) : ds `f1` [a] 

我知道這是更長的時間,但與熊我。 f1f2確實相同,但是對比發生了變化。讓我們的函數no否定的比較,使(no (>=)) x y = not (x >= y)

no cmp x y = not (cmp x y) 

事實上,我們可以把這個作爲

no = ((not.).) 
r = reverse 

func' (a:ds) = f (>=) ds [a] 
f :: Ord a => (a -> a -> Bool) -> [a] -> [a] -> [[a]] 
f _ [] ys = [r ys] 
f cp (a:ds) [email protected](b:es) | cp a b = f cp ds (a:ys) 
         | True = r ys : f (no cp) ds [a] 

現在短。

+0

有趣的解決方案,我想到一個解決方案將f函數包裝成一個改變比較,但不能解決它,因爲我只是一個初學者。 ^^ 謝謝你。 – Timotheus

+0

啊,我剛剛發現,我必須改變> = = <=。那是我錯了。 這裏只有問題。 no函數現在將> =轉換爲<並且不轉換爲<= – Timotheus

+0

OK,傳遞一個'Bool',而不是'a - > a - > Bool',並使用'not'而不是'no'。接下來替換後衛'| cp a b'加上'| leq cp a b'並分別定義'leq True =(<=)'和'leq _ =(> =)'。最後,'func''(a:ds)= f False ds [a]'。 – AndrewC

2

你有比縮進更根本的問題:一個where塊是本地的函數的情況。您正在嘗試使用您的where塊來爲一大堆函數提供綁定(例如,a,b,c,d)。這不起作用。

爲了澄清,這縮進格式正確代碼將無法正常工作:

foo :: Int -> Int 
foo 0 = a 
foo 1 = b 
    where a = 2 
     b = 3 

你會得到一個錯誤,如Not in scope: `a'。這是因爲where只覆蓋foo 1的情況;它甚至沒有進入foo 0的情況,更不用說其他功能了。

另一方面,您的代碼似乎預計where區塊可用於全部您的功能。要具有不同功能可以看到的綁定,必須將它們放在與功能本身相同的範圍。

此外,Haskell縮進是一個有點finnicky。你真的應該避免製表符;它也確實有助於讓編輯正確理解Haskell。我發現Emacs在這裏非常好 - 我從不必擔心使用Emacs的Haskell縮進。

Emacs可能有一點學習曲線(你應該做這個教程),但我認爲它非常值得。你還必須安裝Haskell模式。如果您獲得最新版本的Emacs,您應該可以使用軟件包管理器來執行此操作。

+0

@AndrewC:哈哈,我的意思是*標籤*,而不是*空格*。接得好。最終,你應該避免手動縮進東西,如果你可以避免它:)。 –

2

這就是它看起來編譯:

func :: Ord a => [a] -> [[a]] 
func xs = f1 d [a] 
f1 [] ys = [c] 
f1 xs ys | a >= b = d `f1` a:ys 
       | otherwise = c: d `f2` [a] 
f2 [] ys = [c] 
f2 xs ys | a < b = d `f2` a:ys 
       | otherwise = c : d `f1` [a] 
      where a = head xs 
         b = head ys 
         c = reverse ys 
         d = tail xs 

所以編譯器,第一次看這樣行的延續後的where子句中的臺詞,當然,你不能有多個=沒有一行中間分號。

你應該從未混合製表符和空格(你不應該永遠使用標籤,實際上)。如果你使用標籤,配置你的編輯器將它們解釋爲八個空格。

而且,where子句僅在最後一個等式範圍內,因此func的前四個等式中沒有a, b, c, d範圍。

+0

我不得不說,我編輯了stackoverflow的縮進,因爲它沒有正確顯示它。所以編譯器的代碼看起來有點不同。 但現在我知道我不必使用標籤,並且不能用於多個功能。 – Timotheus