2011-03-17 34 views
2

我想有一個檢查一個類實例的屬性功能:哈斯克爾類屬性檢查

class ListWithAtLeastOneElement a where 
    list :: [a] 
    check :: Bool 
    check = (length list) >= 1 

但GHC編譯時我得到這個錯誤: 「類方法‘檢查’提到無類ListWithAtLeastOneElement的類型變量a當檢查類方法時:check :: Bool在「ListWithAtLeastOneElement」的類聲明中「

有沒有更好的方法來做我想做的事,或者一種方法來獲取它在GHC中編譯?

回答

3

您似乎認爲Haskell中的類就像OO語言中的類。那是不正確的。您應該使用數據類型或新類型或類型同義詞。

newtype NonemptyList a = List1 [a] 

fromList :: [a] -> Maybe (NonemptyList a) 
fromList []  = Nothing 
fromList [email protected](_:_) = Just $ List1 xs 

check :: NonemptyList a -> Bool 
check (List1 xs) = length xs >= 1 
+0

小問題:最好檢查列表是不是空值而不是檢查長度。但是像TomMD的答案那樣創建一個新的數據類型會更好。 – 2011-03-17 18:08:11

+0

@John:創建新數據類型的更好取決於上下文。如果需要經常轉換到標準列表和從標準列表轉換,則新類型的包裝可能會更好。但我同意'不'空'會更好。我想保留原始帖子代碼至少一個細節。 – jmg 2011-03-18 15:20:30

1

你需要做檢查的功能

檢查:: [A] - >布爾

那說你是一個數據類型更好的非空列表,而不是一個類,類在Haskell中與面嚮對象語言中的類沒有相同的用途。

2

正如jmg所說,這是無效的Haskell所以它是好的GHC不編譯它!如果你習慣了Java,顯然你應該考慮Haskell的類型類,比如Java接口。如果這沒有幫助,那麼也許你應該閱讀LYAH's chapter on classes

對於你的問題,你似乎想要一個永遠不能爲空的列表式數據類型。你並不需要測試對於這樣的屬性,可以靜態地確保它通過使用數據 類型不能爲空:

-- Notice this data type can never have zero 'a' values! 
data NonEmptyList a = NEL a (NonEmptyList a) | Singleton a 

-- We can define basic operators for this, just like list has 
-- You can't pattern match with them, but there are work-arounds for that if you want to ask 
(.:) = NEL -- concatenate non-empty lists 

nelHead :: NonEmptyList a -> a 
nelHead (NEL a _) = a 
nelHead (Singleton a) = a 

nelTail :: NonEmptyList a -> Maybe (NonEmptyList a) 
nelTail (NEL _ b) = Just b 
nelTail _ = Nothing 

nelTake :: Int -> NonEmptyList a -> NonEmptyList a 
nelTake 1 (NEL a _) = Singleton a 
nelTake 1 (Singleton a) = Singleton a 
nelTake n (NEL a rest) = a .: nelTake (n-1) rest 

nelDrop :: Int -> NonEmptyList a -> NonEmptyList a 
nelDrop _ (Singleton _) = error "Perhaps I should have used the 'maybe' type" 
nelDrop 1 (NEL a r) = r 
nelDrop n (NEL a r) = nelDrop (n-1) r 

等等等等。值得注意的是nelTakenelDrop是部分的,但是nelHead是總的,很有趣,因爲這與常規列表相反。

+0

這在功能語言中通常是很好的做法 - 不是說「它是一個列表,除了...」,請設計您的數據類型以通過構造*來獲得屬性*。儘管如果你有很多操作需要支持,它可能會更多一些。 – luqui 2011-03-17 17:24:35