4

実行を「表示」するためのモノイドを含むアプリケーションファンクターに取り組んでいます。ただし、この部分がまったく気にならない場合もあるため、モノイドの選択は、決して消費されないため意味がありません。私が持っているものを単純化しました:

{-# 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

Renderaさまざまなを単一のに変換するために使用されbます。Merge私の実際のファンクターを大幅に単純化したものですが、要点は、型ファミリー/制約が含まれていることであり、その意図はRenderMerge必要なものを正確に指定することです。

ここで、 を「実行」したいかもしれませんが、Merge次のようなビューを破棄します。

runFoo :: Merge a => a -> Int
runFoo x = case merge x of () -> 5

しかし、これは次の理由で失敗します。

(Renderer a ())の使用から生じると推測できませんでしたmerge

()forallaのインスタンスがあるため、モノイドとして選択しましたRender a ()。したがって、それがMerge a単にコレクションのRender制約を意味すると言う方法があれば、これはうまく機能します。もちろん、Merge aそれよりも一般的です-コンパイルエラーを説明する任意の制約を追加できます。

の署名を変更せに、私が望むものを達成する方法はありrunFooますか?

4

1 に答える 1

5

これらのケースが多数ある場合、これは拡張できない可能性がありますが、これは機能します。

class Renderer a () => Merge a where
  ...
于 2013-01-04T15:19:44.480 に答える