2016-12-12 61 views
2

我想有這個漂亮的,乾淨的方式來描述一個對象的功能和模式匹配特性:函數聲明在多行

data Animal = Cat | Dog | Cow 

isBig :: Animal -> Bool 
isLoyal :: Animal -> Bool 
-- many more possible properties, including complicated non-bools, methods, and whatnot 


--- Describing Cat 

isBig Cat = False 
isLoyal Cat = False 
--- more properties 


--- Describing Dog 

isBig Dog = False 
isLoyal Dog = True 
--- more properties 


--- Describing Cow 

isBig Cow = True 
isLoyal Cow = False 
--- more properties 

然而,這給出了關於多個聲明錯誤。因爲,顯然,通過模式匹配的功能定義必須在連續的行中完成。

這是否表明我的方法是錯誤的,類似於Haskell?或者這只是語言中的缺陷?或者我誤解了一些東西?

+1

在這種情況下,它沒有任何意義 - 或者我會在我的答案也提到了 - 但也許你的問題的情況下是一個什麼樣你實際上是試圖做的簡化。如果是這樣,你可以考慮製作一個包含'isBig','isLoyal'等的類型類,並且製作實現這個類的_types_'Dog','Cat'和'Cow'類。然而,這是非常不同的:與類型不同,類是開放的。 –

回答

5

這既不是語言上的缺陷,也不表示您的方法是錯誤的。這只是一個句法限制,作爲一個必須以某種方式或某種方式做出的討厭設計決定的一部分。

限制的吸引力在於,它意味着在閱讀代碼時,人們不必擔心他們錯過了部分值的定義,因爲它分佈在當前文件的很遠處。儘管如此,它確實阻止了一些完美的邏輯組織代碼的方式,包括您目前正在嘗試使用的方法。

真可惜,我們不能同時擁有!

人們可以考慮做這樣的事情:

data Stats = Stats 
    { isBig :: Bool 
    , isLoyal :: Bool 
    , -- ... 
    } 

stats :: Animal -> Stats 
stats Cat = Stats 
    { isBig = False 
    , isLoyal = False 
    } 
+0

然後,如何組織一段代碼就是一個好方法? – user2649762

+0

@ user2649762我在您可能喜歡的一種方法上添加了一個想法。 –

+0

謝謝,還有一件事。有很多屬性,其中大多數都沒有爲所有的動物定義。我有'isLoyal _ = False; isBig _ = False「,這樣如果我沒有爲一個Animal定義一個特定的屬性,它只是默認爲一個值。如何用你的方法實現這個? – user2649762

2

報價Section 4.4.3.1 of the Haskell Report

4.4.3.1功能綁定

函數綁定綁定到一個函數值的變量。函數爲變量x結合的一般形式是:

[規範函數綁定的語法,覆蓋所述多個子句場景。]

注意,定義一個函數的所有條款必須是連續的,並且數每個子句中的模式必須相同。 [...]

您已經注意到的限制是「所有定義函數的子句必須是連續的」。 Daniel Wagner的答案討論了這一設計決定背後的可能理由。我想,特別強調的是,忘記對應於類型的構造函數中的一個條款是一個相當危險的錯誤,這會更容易犯是否有可能掰開條款在你的建議(一個函數,它的方式預計Animal將處理所有三種可能性)。