私はgenerics-sopに直接ジェネリックを使用するのではなく、このような問題について説明します。 generics-sopは、ジェネリックスの上に構築され、レコード内のすべてのフィールドを統一的に操作する機能を提供します。
私は
ベースが付属していますが、他の
Applicative
パーサがどうなる
ReadPパーサーを使用この答えで
。いくつかの予備的な輸入:
{-# language DeriveGeneriC#-}
{-# language FlexibleContexts #-}
{-# language FlexibleInstances #-}
{-# language TypeFamilies #-}
{-# language DataKinds #-}
{-# language TypeApplications #-} -- for the Proxy
import Text.ParserCombinators.ReadP (ReadP,readP_to_S)
import Text.ParserCombinators.ReadPrec (readPrec_to_P)
import Text.Read (readPrec)
import Data.Proxy
import qualified GHC.Generics as GHC
import Generics.SOP
は、我々はそのインスタンスごとにApplicative
パーサを生成することができます型クラスを定義します。ここでは、Int
とBool
のためだけのインスタンスを定義します。
class HasSimpleParser c where
getSimpleParser :: ReadP c
instance HasSimpleParser Int where
getSimpleParser = readPrec_to_P readPrec 0
instance HasSimpleParser Bool where
getSimpleParser = readPrec_to_P readPrec 0
今、私たちはすべてのフィールドがHasSimpleParser
インスタンスを持っているレコードの一般的なパーサを定義します。
recParser :: (Generic r, Code r ~ '[xs], All HasSimpleParser xs) => ReadP r
recParser = to . SOP . Z <$> hsequence (hcpure (Proxy @HasSimpleParser) getSimpleParser)
Code r ~ '[xs], All HasSimpleParser xs
制約はこのタイプが持っている」という意味します1つのコンストラクタのみ、フィールドタイプのリストはxs
、すべてのフィールドタイプはHasSimpleParser
のインスタンスです。
hcpure
は、対応するフィールドのパーサーであるr
のパーサであるn進数の積()を構成します。 (NP
の製品では、各コンストラクタを型コンストラクタにラップします(この場合、パーサータイプはReadP
)。
次に、n-ary製品のパーサにn-aryパーサーを変換するためにhsequence
を使用します。
最後に、得られたパーサにfmapを実行して、元のr
レコードに戻ります(to
を使用)。 Z
およびSOP
のコンストラクタは、n-ary積を関数sumが期待する積に変換するために必要です。
OK]をクリックして、のは、例のレコードを定義し、それをGenerics.SOP.Generic
のインスタンスを作成してみましょう:
data Foo = Foo { x :: Int, y :: Bool } deriving (Show, GHC.Generic)
instance Generic Foo -- Generic from generics-sop
は、私たちがrecParser
でFoo
を解析することができるかどうかは確認してみましょう:
main :: IO()
main = do
print $ readP_to_S (recParser @Foo) "55False"
結果が
です
[(Foo {x = 55, y = False},"")]
ジェネリックスがこれを行うことができます。 attoparsecのようなものの上にジェネリックパーサを構築し、 'Generic'を実装するためのデフォルトの実装を提供する' Parseable'型のクラスを作ることができます。それから、 'インスタンスParseable User where'が解析できるようにするだけです。 – bheklilr
お役立ち情報詳細はどこで確認できますか?私はGoogleの "attoparsec一般的なparsable"しかし、検索結果は非常に有用ではなかった。 – user2812201
'Parsable'は自分で書くタイプクラスです。 Attoparsecは、テストリングを解析するのにまともなライブラリです。 Genericは組み込みのtypeclassで、コード内で操作できるデータ型の汎用表現を取得する関数を提供します。たとえば、aesonは 'Generic'を利用できる' FromJSON'型のクラスを提供していますので、JSONを 'MyType'の値にパースする能力を得るために余分な作業をせずに' instance FromJSON MyType where'を実行できます。 – bheklilr