2012-03-13 10 views
2

URLを生成するためにブーメランを正しく使用する方法について少し混乱しています。私は、次のしている:単純な代数データ型のweb-routes-boomerang

data State = 
    AK | AL | AR | AZ | CA ... WY 

data Sitemap 
    = Home 
    | State State 
    | Place State String 
     deriving (Eq, Ord, Read, Show, Data, Typeable) 

$(derivePrinterParsers ''Sitemap) 

sitemap ∷ Router Sitemap 
sitemap = 
    ( rHome 
    <> rState . state 
    <> rPlace . (state </> anyString) 
    ) 

state :: PrinterParser StringsError [String] o (State :- o) 
state = xmaph read (Just . show) anyString 

これが動作しているようですが、私はarticleIdのドキュメント内の1つでstateの私の実装を比較するとき、彼らは反対のファッションで働いているように見える:

articleId :: Router ArticleId 
articleId = xmaph ArticleId (Just . unArticleId) int 

タイプはまったく異なり、反対方向に向かっているように見えますが、私のsitemapが機能し、アプリケーションがURLを正しく処理します。

maybeState :: String → Maybe State 
maybeState stateString = case reads stateString of 
        [(state, "")] -> Just state 
        _    -> Nothing 

stateR :: Router State 
stateR = xpure show maybeState 

これはチェック型、それでもその定義についてundefinedに置き換えて、上記sitemapで、rState . stateRは動作しますが、rPlace . (stateR </> anyString)しませんしません:私はそれがより次のようになりますだと思います。

私はこれを世話するライブラリ機能が十分にあると思われますが、私は見たことがありませんでした。

編集:ここでは型エラーのいくつかは、私が取得:

state = xpure show maybeStateについて:state = undefined :: Router Stateについては

Main.hs:56:16: 
    Couldn't match expected type `State :-()' 
       with actual type `[Char]' 
    Expected type:() -> State :-() 
     Actual type:() -> String 
    In the first argument of `xpure', namely `show' 
    In the expression: xpure show maybeState 

(このエラーがsitemap定義である):

Main.hs:45:18: 
    Couldn't match expected type `String :-()' with actual type `()' 
    Expected type: PrinterParser 
        StringsError [String]() (State :- (String :-())) 
     Actual type: Router State 
    In the first argument of `(</>)', namely `state' 
    In the second argument of `(.)', namely `(state </> anyString)' 

答えて

1

で州を使用しているため、タイプが異なって見えます。行には、Routerエイリアスの許可よりも一般的な型の署名が必要です。 (あなたのコードは大丈夫ですが、おそらく我々は、しかしブーメランで、より一般的なエイリアスを提供する必要があります..)

あなたがする状態の型シグネチャを変更することができrPlace行削除する場合:あなたの場合は

state :: Router State 
state = xmaph read (Just . show) anyString 

をもっと詳しく見ると、statearticleIdが実際に同じ方向に向いていることがわかります。

articleId :: Router ArticleId 
articleId = xmaph ArticleId (Just . unArticleId) int 

第3引数のxmaphは、基本的な値を解析する方法を指定します。 articleIdの場合は、intを解析し、stateの場合はanyStringを解析します。

xmaphの最初の引数は、その値を目的の戻り値の型に変換する方法を指定します。 articleIdでは、単純にArticleIdコンストラクタを適用します。 stateでは、read関数を適用します。しかし、我々は目的の戻り値の型に根本的な価値から行くの両方のケースで:

ArticleId :: Int -> ArticleId 
read  :: String -> State 

xmaphの二番目の引数は戻って基本的な値に戻り値の型を変換する方法を指定します。潜在的に失敗し、エラーによる可能性が「読み取り」ので、我々は実際に使用してはならないと述べた

show  :: State  -> String 
unArticleId :: ArticleId -> Int 

は、とにかくここに「読み取り」。 xmaphへの最初の引数は完全な関数になることを意図しています。

readshowという名前のStringsモジュールに新しいコンビネータを追加したboomerang 1.3.1をアップロードしました。この関数は、ReadインスタンスとShowインスタンスを正しく使用します。残念ながら、エラー報告はちょっとうんざりです。なぜならreadsが失敗すると、それがなぜ、どこで失敗したかはわかりません。

state :: PrinterParser StringsError [String] o (State :- o) 
state = readshow 

を私たちは、無効な状態を供給した場合、我々は今取得:

> parseStrings sitemap ["AZ"] 
Right (State AZ) 
> parseStrings sitemap ["FOEU"] 
Left parse error at (0, 0): unexpected FOEU; decoding using 'read' failed. 
+0

私には驚くべきである何、私は推測であり、しかし、それはあなたが今書くことができることを使用して:)

何もないよりはましです文字列から状態への変換は、状態から文字列への変換ではなく、失敗する可能性があります。私は 'read'を使ってちょっと汚いと感じます - ブーメランが私のために例外をスローする読み込みの可能性を処理していますか?文字列全体の代わりに2文字を引っ張るべきですか? –

+0

ええ、あなたは実際にそこに読んで使ってはいけません。私はあなたが望むことをする新しいreadshowコンビネータを追加しました。 xmaphへの最初の引数は常に成功しなければなりません(別名、総関数です)。 おそらく 'xmaph'の最初の引数は' Maybe/Either'関数でなければなりません。たとえば、 'articleId'はintが負の値であれば失敗する可能性があります。もっと考えてみる必要があります。 これに対して、xmaphはfmapの双方向バージョンのようになり、fmapは単にa-> b'となります。しかし、それはなぜ我々が '(b - >たぶんa)'を持っているのかを説明していない。 – stepcut

+0

恐ろしく、ありがとう! –

関連する問題