2011-03-17 9 views
2

내가 클래스 인스턴스의 속성 확인하는 기능을 가지고 싶다 :하스켈 클래스 속성 검사

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

을하지만, GHC에서 컴파일 할 때이 오류가 발생합니다 : "클래스 방법은 '확인'은 전혀 언급하지 ListWithAtLeastOneElement 클래스의 유형 변수의 경우 : check :: Bool 'ListWithAtLeastOneElement'에 대한 클래스 선언에서 "

내가 원하는 것을 수행하는 더 좋은 방법이나이를 얻는 방법이 있습니까? GHC에서 컴파일 하시겠습니까?

답변

3

하스켈의 수업은 OO 언어의 수업과 같다고 생각되는 것 같습니다. 그건 사실이 아니야. 데이터 유형이나 newtype 또는 type 동의어를 사용해야합니다.

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

사소한 단점 : 길이를 확인하는 대신 목록이 'not null'인지 확인하는 것이 좋습니다. 그러나 TomMD의 답변 에서처럼 새로운 데이터 유형을 만드는 것이 더 좋을 것입니다. –

+0

@ John : 새로운 데이터 형식을 만드는 것은 상황에 따라 더 좋습니다. 자주 표준 목록으로 변환하거나 표준 목록에서 변환해야하는 경우, newtype 래퍼가 더 좋습니다. 그러나 나는 'not null'이 더 좋을 것이라는데 동의한다. 원본 게시물 코드를 적어도 하나 이상 자세하게 유지하려고했습니다. – jmg

1

당신은 함수를 확인해야 할 것

검사 :: [A] -> 당신이 비어 있지 않은리스트가 아닌 클래스, 클래스에 대한 데이터 유형이 더 낫다 말했다 BOOL

하스켈에서는 객체 지향 언어의 클래스와 같은 목적을 수행하지 않는다.

2

jmg이 말했듯이 이것은 유효하지 않은 하스켈이므로 GHC는 컴파일하지 않습니다. Java에 익숙하다면 하스켈의 Java 인터페이스와 같은 유형 클래스를 생각해야합니다. 도움이되지 않는다면 LYAH's chapter on classes을 읽어야합니다.

문제가 있으면 null이 될 수없는 목록과 같은 데이터 형식이 필요합니다. 당신은 당신이 정적으로 비어있을 수 없다 데이터 유형을 사용하여 보장 할 수 있습니다, 이러한 속성에 대한 테스트 할 필요가 없습니다 : 등

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

이것은 일반적으로 함수형 언어에서 좋은 습관입니다 - "it 's a list, except ..."라고 말하는 대신 데이터 형식을 * by construction * 속성으로 지정하십시오. 지원해야 할 작업이 많으면 좀 더 상용구가 될 수 있습니다. – luqui