次のコンストラクターがある場合:
data Garage = Gar String
タイプが私のガレージタイプと等しいかどうかをテストしたい場合は、次のようにします。
(==(Gar _)) (Gar "g")
ただし、コンパイラはアンダースコアについて文句を言います。これを置き換えると"g"
、が返されますTrue
。ワイルドカードと比較できる方法はありますか?
次のコンストラクターがある場合:
data Garage = Gar String
タイプが私のガレージタイプと等しいかどうかをテストしたい場合は、次のようにします。
(==(Gar _)) (Gar "g")
ただし、コンパイラはアンダースコアについて文句を言います。これを置き換えると"g"
、が返されますTrue
。ワイルドカードと比較できる方法はありますか?
コードが機能しないのはなぜですか?
パターンマッチをしたいように見えますが、実際には==
引数Gar _
とを指定して関数を呼び出していますGar "g"
。そのため、Haskell は混乱して、「式コンテキストのパターン構文: _」のようなことを言います。
どうすれば修正できますか?
あなたはできる:
deriving Eq
データ宣言の最後に追加する、または
自分で実装しEq
ます:
instance Eq Garage where
(Gar l) == (Gar r) = l == r
コンストラクターのワイルドカードに対してパターン マッチを行うことは可能ですか? (完全を期すために)
はい、ここにナンセンス関数があります:
f :: Garage -> Int
f (Gar "abc") = 12
f (Gar _) = 4
ただし、これはおそらく、複数のコンストラクターを持つデータ型でより便利です。
次のように、パターン マッチを実行します。
case x of
Gar _ -> True
_ -> False
関数として必要な場合は、次のようなものを追加します
isGarage (Gar _) = True
isGarage _ = False
あなたの質問は、Haskell で実行時の型チェックを行う必要があると想定しているかもしれませんが、それは必須ではありません。Haskell は、コンパイル時にすべての型が正しいことを確認するため、データがGarage
データ型の一部であるかどうかをチェックする関数は必要なく、機能しません。
justPrintGarages (Gar x) = print x -- if the argument is a Garage, print its content
justPrintGarages _ = return () -- if it's anything else, do nothing.
ghci にどんな型justPrintGarages
があるか尋ねると、答えてくれます
printGarages :: Garage -> IO ()
うわぁ!ガレージがあるかどうかを教えてくれるはずだった私たちの関数は、ガレージでしか機能しませんか??? うん。これは、Haskell が故意に型を混同しないようにするためです。これは実行時エラーの泥沼であるためです。静的型付けはあなたの友達です。静的型付けは苦痛の世界を取り除きます。静的型付けのため、定義できません
printGaragesAndShebangs (Gar x) = print x
printGaragesAndShebangs ('#':'!':xs) = putStr xs
printGaragesAndShebangs _ = return ()
型エラーが発生します。String
s とs を同じように扱うことはできませんGarage
。
ガレージと文字列を混在させたい場合は、型の安全性を保ちながら次のようにします。
data GarageStringInt = GsiG Garage | GsiS String | GsiI Int
(GarageStringInt
は恐ろしい名前であり、GisG
その他も同様ですが、コードでこれが必要な場合は、意味のあるものを表し (願っています)、それが何を表すかを説明する名前を付けることができます。)
今、私たちは書くことができます
printGaragesAndShebangs :: GarageStringInt -> IO ()
printGaragesAndShebangs (GsiG (Gar x)) = print x
printGaragesAndShebangs (GsiS ('#':'!':xs)) = putStr xs
printGaragesAndShebangs _ = return ()
のような関数
isGarage (Gar _) = True
isGarage _ = False
type を持っているので、かなり役に立ちませんGarage -> Bool
。True
そのため、型に対しては常に返されGarage
、他の型に対しては型チェックの失敗が発生します。
あなたの要件にはパターンマッチングで十分だと思います。ただし、操作する型がわかっている場合は、型クラスを使用してそのような種類の関数を使用できることを示すためだけに。したがって、特定のタイプのセットから値を取得することがわかっている場合は、次のようなことができます
{-# LANGUAGE FlexibleInstances #-}
data Garage = Gar String
class IsGarage a where
isGarage :: a -> Bool
isGarage _ = False
instance IsGarage Garage where
isGarage _ = True
instance IsGarage [Char]
ghciで
*Main> :t isGarage
isGarage :: IsGarage a => a -> Bool
*Main> isGarage "3"
False
*Main> isGarage (Gar "2")
True