2

以下の圏論用語の誤用の可能性が高いことをお許しください。手がかりの半分を持っているように見える場合、私は自分が大成功を収めたと判断します。

複数のアリティの型コンストラクターの積を処理する一連のクラスを作成していることに気付きました。このようなもの:

import Control.Applicative

-- | RWS monad.
newtype RWS r w s a = RWS {runRWS :: r -> s -> (a, s, w)}

-- | A class for unary type constructors that support a Cartesian
-- product operation.
class ProductObject f where
    (***) :: f a -> f b -> f (a, b)
infixr ***

-- | Example instance of 'ProductObject'.
instance ProductObject [] where
    (***) = liftA2 (,)


-- | A class for binary type constructors (read as morphisms
-- between their type parameters) that support a product morphism
-- operation.
class ProductMorphism arrow where
    (****) :: arrow a b -> arrow c d -> arrow (a, c) (b, d)
infixr ****

-- | Example instance of 'ProductMorphism'.  
instance ProductMorphism (->) where
    f **** g = \(a, c) -> (f a, g c)


-- | A class for ternary type constructors (read as two-place
-- multiarrows @a, b -> c@) with products.
class ProductMultimorphism2 arr2 where
    (*****) :: arr2 a b c -> arr2 d e f -> arr2 (a, d) (b, e) (c, f)
infixr *****


-- | A class for ternary type constructors (read as two-place
-- multiarrows @a, b -> c@) with products.
class ProductMultimorphism3 arr3 where
    (******) :: arr3 a b c d -> arr3 e f g h -> arr3 (a, e) (b, f) (c, g) (d, h)
infixr ******

-- | Let's pretend that the 'RWS' monad was not a type synonym
-- for 'RWST'.  Then an example of 'ProductMorphism3' would be:
instance ProductMultimorphism3 RWS where
    f ****** g = RWS $ \(fr, gr) (fs, gs) ->
        let (fa, fs', fw) = runRWS f fr fs
            (ga, gs', gw) = runRWS g gr gs
        in ((fa, ga), (fs', gs'), (fw, gw))

さて、これはいくつかの理由で面倒です。最大の問題は、アプリケーション内の型の 1 つを修正して 3 番目のパラメーターを追加する必要があることです。****つまり、その型の の使用をすべて見つけて、 に変更する必要があり*****ます。

この状況を緩和するために適用できるトリックはありますか? GHC でこれが適用されるかどうかを理解しようとしていますが、(a) ゆっくり進んでいます。(b) GHC 7.4.x ではバグがPolyKindsあると聞いています。PolyKinds

4

1 に答える 1

0

さて、私は自分でそれを理解しました:

{-# LANGUAGE MultiParamTypeClasses, TypeFamilies #-}

import Control.Applicative

class Product f g where
    type Prod a b :: *
    (***) :: f -> g -> Prod f g


instance Product [a] [b] where
    type Prod [a] [b] = [(a, b)]
    (***) = liftA2 (,)

instance Product (a -> b) (c -> d) where
    type Prod (a -> b) (c -> d) = (a, c) -> (b, d)
    f *** g = \(a, c) -> (f a, g c)
于 2012-12-05T22:03:21.077 に答える