パターンを述語関数として使用する便利な方法はありますか?


10

私は最近、述語関数を別の関数に渡す必要がある状況に遭遇しており、私が探しているロジックは、基本的に「この値がこのパターンに一致するか」というものです。

宣言、doブロック、リスト内包表記ではパターンマッチングが推奨されるようですが、述語を使用する関数がいくつかありa -> Bool、パターンを何らかの方法で渡すと非常に便利です。たとえば、takeWhileuntilfindspan、など

これまでのところ、私は\a -> case a of MyCons _ -> True; otherwise -> False名前付き関数のアラを書いてきましたlet myPred (MyCons _) = True; myPred _ = False inが、どちらもひどく醜く、あまり慣用的ではないようです。「明白な」(そして間違った)方法は、次のようなものです\(MyCons _) -> Trueが、当然、部分的であるためにエラーをスローします。

この種のことを行うためのより簡潔でクリーンな方法はありますか?または私は物事を完全に間違った方法で行っていますか?


1
多分これは「個人的な趣味」かもしれませんが、この述語が1か所で必要なだけなら、let嫌いな節でかなり満足します-同等のwhere節を好むので、これは主な定義を混乱させません。もちろん、このユーティリティが2回以上必要になる場合は、トップレベルの関数として定義します。
ロビンジグモンド

それは確かにうまくいきます。私の質問は、Haskellが典型的にどれほど印象的に簡潔であるかによってやや動機づけられました。通常、慣用的なHaskellにはアイデアの重複がほとんどなく、綿毛が最小限に抑えられているように感じられます。したがって、let myPred...スタイルが悪いと思うことは必ずしも必要ではありませんが、非常に単純なアイデアに期待するよりもはるかに冗長に感じられます。
David Sampson

2
あなたは(レンズから)プリズムを見ているかもしれません。彼らは一流の
コンポーズ

1
このタイプの高階関数を使用している例を見る必要があると思います。私の一部は、問題はそもそもそのような述語を必要とするデザインにあると言いたいです。
chepner

Haskell98の方法は、このために、同じように、あなたのデータ型の場合、マッチング(解体)関数を定義することであるmaybe :: b -> (a -> b) -> Maybe a -> bbool :: a -> a -> Bool -> a、引数(複数可)としての機能(複数可)ブール生産とそれを使用しています。たとえばmyCons z f (MyCons x) = f x ; myCons z f _ = z、次に呼び出しますmyCons False (const True) aMyConsValue。これはあなたが書いたものとほぼ同じで、関数の引数を介してベイクされた「間接」/「抽象化」のもう1つのレベルがあります。
ウィルネス

回答:


7

言語拡張機能LambdaCaseを使用してを使用できますが、\case MyCons _ -> True; _ -> Falseこれはそれほど多くの文字を保存しません。

私は、あなたが一連の機能を書くことができると信じてconstructedWith :: (Generic a) => (b -> a) -> a -> BoolconstructedWith2 :: (Generic a) => (b -> c -> a) -> a -> Boolしかし、私は数時間で物事をテストすることなく、それを実装するためにジェネリックで有能十分ではありませんよ。私はこれを試し、それが理解できる場合、または行き止まりである場合は、私の答えを編集します。

編集:はい、あなたはそれを行うことができます!ここに私のコードへのリンクがあります、それはそれをすべてゼロから実装します:

https://repl.it/@lalaithion/ConstructedWith

ただし、すべての汎用コードの配管にhttp://hackage.haskell.org/package/generic-deriving-1.13.1/docs/Generics-Deriving-ConNames.htmlのようなものを使用する方が良い場合があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.