私は、実行を「見る」ためにモノイドを含む応用ファンクタに取り組んでいます。しかし、時には私はこの部分をまったく気にしないので、モノオイドの選択は決して消費されないので無関係です。制限付きの制約タイプとタイプファミリーを '限定された'制約付きで使用する
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
import GHC.Exts
class Render a b where render :: a -> b
instance Render a() where render = const()
class Merge a where
type Renderer a b :: Constraint
merge :: Renderer a b => a -> b
data Foo = Foo Bool
instance Merge Foo where
type (Renderer Foo) m = (Render Bool m)
merge (Foo b) = render b
Render
は単一b
に様々なa
Sを変換するために使用されています。私は私が持っているものに簡略化されてきました。 Merge
は私の実際のファンクタを大幅に簡略化していますが、それは型のファミリ/制約が含まれており、その意図は正確にRender
とMerge
が必要とするものを指定することです。
さて、私のようなものに似ている、「実行」Merge
したいのですが、ビューを捨てるかもしれません:
runFoo :: Merge a => a -> Int
runFoo x = case merge x of() -> 5
しかしので、これは失敗します。
は推測できませんでした私はFなぜなら私のモノイドとして
()
を選んだmerge
の使用に起因する(Renderer a())
orall a
の場合、Render a()
というインスタンスがあります。だから、もしMerge a
がコレクションRender
のコレクションを意味すると言うならば、これはうまくいくでしょう。もちろん、Merge a
より一般的です。コンパイルエラーを説明する任意の制約を追加する可能性があります。
なしでの署名を変更するととにかくありますか?runFoo
の署名を変更しますか?
は 'Renderer'は常に1つ' Render'が含まれていますか? –
@Tinctorius - いいえ、一般的に 'Foo'のフィールドにある別個の型の量に依存します – ocharles
' Merge'に 'b'もパラメータとして持たない理由はありますか? –