문제

타입 X 다음과 같이 정의됩니다.

data X = 
    X { sVal :: String } |
    I { iVal :: Int } |
    B { bVal :: Bool }

그리고 나는 원한다 Int 안에 X 값, 그렇지 않으면 0이있는 경우 값.

returnInt :: X -> Int

어떤 유형의 유형을 결정할 수 있습니까? X 논쟁 returnInt 이다?

도움이 되었습니까?

해결책

여기서 점을 명확히하기 위해 x의 의미에서 모호성을 피하기 위해 데이터 유형을 다시 작성하겠습니다.

data SomeType = X { myString :: String} | I {myInt :: Int} | B {myBool :: Bool}

이 정의에는 x, i 및 b 유형이 없습니다. x, i 및 b입니다 유형 값을 만드는 생성자 Sometype . GHCI에게 해당 유형 생성자로 구성된 값의 유형이 무엇인지 물어 보면 어떻게되는지 확인하십시오.

*Main> :t (I 5)
(I 5) :: Sometype 

*Main> :t (B False)
(B False) :: Sometype

그들은 같은 유형에 속합니다 !!

X, I 및 B를 사용하여 유형을 구성 할 수있는 것처럼 패턴 매칭을 사용하여 위의 다른 답변에서 수행 한 것처럼 유형을 해체 할 수 있습니다.

returnInt :: SomeType -> Int 
returnInt (I x) = x        -- if the pattern matches (I x) then return x
returnInt _  = error "I need an integer value, you moron"  -- throw an error otherwise

패턴 일치는 순서대로 발생한다는 것을 기억하십시오. 값이 일부 줄의 패턴과 일치하면 아래 줄의 패턴이 실행되지 않습니다.

당신이했던 것처럼 유형을 정의 할 때, 레코드 구문을 사용하는 것을 사용하십시오 (여기서보십시오. http://en.wikibooks.org/wiki/haskell/more_on_datatypes ), 당신은 무료로 그런 기능을 받았습니다 !!

예를 들어, MyInt의 유형을 살펴보십시오.

*Main> :t myInt
myInt :: SomeType -> Int

이 기능이 무엇을하는지보십시오.

*Main> myInt (I 5)
5

*Main> myInt (B False)
*** Exception: No match in record selector Main.myInt

이것은 정확히 행동입니다 returnInt 위의 정의. 이상한 오류 메시지는 기능이 일치하지 않는 유형의 구성원을 처리하는 방법을 모른다는 것을 알려줍니다. (I x).

보다 일반적인 구문을 사용하여 유형을 정의하는 경우 :

data SomeType2 = X String | I Int | B Bool

그런 다음 멋진 레코드 기능을 풀어줍니다.

오류 메시지는 프로그램 실행을 종료합니다. 이것은 때때로 성가신 일입니다. 당신의 기능에 대해 더 안전한 행동이 필요하다면 Gbacon의 대답은 단지 그것을하는 방법입니다. 에 대해 알아보십시오 Maybe a 일부 가치를 반환하거나 아무것도 반환 해야하는 이런 종류의 계산에 대처하기 위해 유형을 사용하여 사용하십시오 (시도해보십시오. http://en.wikibooks.org/wiki/haskell/hierarchical_libraries/maybe ).

다른 팁

패턴 매칭을 사용하십시오.

returnInt :: X -> Int
returnInt (I x) = x
returnInt _     = 0

가능한 모든 것에 대해보다 유연한 정의를 사용하십시오 X 값 :

returnInt :: X -> Maybe Int
returnInt (I i) = Just i
returnInt _ = Nothing

그런 다음 사용할 수 있습니다 maybe 원하는 특정 불이행의 경우 0은 유효한 값일 수 있습니다 (이것은 반드시 문제):

*Main> maybe 0 id (returnInt $ X "")
0
*Main> maybe 0 id (returnInt $ I 123)
123
*Main> maybe (-1) id (returnInt $ X "yo")
-1

대조적으로, 부분 함수는 위험 런타임 예외 :

*Main> let returnInt (I i) = i
*Main> :t returnInt
returnInt :: X -> Int
*Main> returnInt (B True)
*** Exception: <interactive>:1:4-22: Non-exhaustive patterns in function returnInt

당신이 정말로 개구리를 느끼고 있다면, 당신은 사용할 수 있습니다 MonadPlus

returnInt :: (MonadPlus m) => X -> m Int
returnInt (I i) = return i
returnInt _ = mzero

더 많은 유연성을 얻으려면 :

*Main> maybe 0 id (returnInt $ X "")
0
*Main> maybe 0 id (returnInt $ I 123)
123
*Main> returnInt (I 123) `mplus` returnInt (I 456) :: [Int]
[123,456]

다음과 같은 기능이 주어지면 :

returnInt :: X -> Int
returnInt x = {- some integer -}

... 유형 x 항상 X. 당신이 신경 쓰는 것은 x 사용 X, I 또는 B 생성자 유형.

패턴 매칭을 사용하여 차이점을 알려줍니다.

returnInt :: X -> Int
returnInt (X _) = error "needed an Int, got a String"
returnInt (I { iVal = n }) = n
returnInt (B _) = error "needed an Int, got a Bool"
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top