質問

入力するとき X と定義されている:

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

そして私はそれが欲しいです Int の中で X 1 がある場合は値、それ以外の場合は 0。

returnInt :: X -> Int

どのタイプかを判断するにはどうすればよいですか X に対する議論 returnInt は?

役に立ちましたか?

解決

ここでの点を明確にするために、X の意味の曖昧さを避けるためにデータ型を書き直させてください。

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

この定義では、X、I、B タイプは存在しません。X、I、B は type の値を作成するコンストラクター 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 上記で定義されています。この奇妙なエラー メッセージは、関数が一致しない SomeType 型のメンバーを処理する方法を知らないことを示しているだけです。 (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を(これは semipredicate問題として知られている有効な値である場合があります):

*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です。あなたが気にすることはxXIまたは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