2017-10-09 3 views
3

Lorsque vous travaillez avec un Bifunctor, nous avons accès aux fonctions "carte" first et second. Donc, fondamentalement, c'est un Functor qui nous permet de fmap de deux façons différentes.Existe-t-il un équivalent Monoid de Bifunctor?

Y a-t-il quelque chose comme ceci pour Monoid? Un concept qui nous permet d'ajouter de deux manières différentes? Par exemple, imaginez un type Matrix opaque. Ce n'est pas une liste de listes ou un vecteur de vecteurs, nous n'avons aucune idée de la façon dont elle est structurée à l'intérieur, mais nous savons que nous pouvons y ajouter des lignes et des colonnes.

Y aurait-il une classe de type autorisée à le faire?

class X a where 
    firstAppend :: a -> a -> a 
    secondAppend :: a -> a -> a 

instance X Matrix where 
    firstAppend = appendRow 
    secondAppend = appendColumn 
+3

Je ne suis pas au courant de la norme de quoi que ce soit défini . Vous pourriez certainement le définir vous-même. Je ne suis pas sûr de la valeur car au niveau du type il n'y a rien à différencier. Je pense qu'une solution plus appropriée pourrait être wrapper 'newtype' et deux instances différentes, semblables à' Product' et 'Sum' dans' Data.Monoid'. – ryachza

+0

Ouais @ryachza Je pense que cela pourrait être une solution plus appropriée. –

+0

Ceci est régulièrement effectué de manière ad hoc, par ex. [dans les diagrammes] (http://hackage.haskell.org/package/diagrams-lib-1.4.1.2/docs/Diagrams-TwoD-Combinators.html#v:-61--61--61-), [matrice ] (http://hackage.haskell.org/package/matrix-0.3.5.0/docs/Data-Matrix.html#g:9) ou [hmatrix] (http://hackage.haskell.org/package/hmatrix -0.18.1.0/docs/Numeric-LinearAlgebra-Data.html # g: 12). – leftaroundabout

Répondre

2

Je suppose que vous pourriez faire quelque chose comme ça avec Monoïdes indexées:

{-# LANGUAGE PolyKinds  #-} 
{-# LANGUAGE KindSignatures #-} 
{-# LANGUAGE TypeFamilies #-} 

module IndexedMonoids where 

class MonoidIx (m :: k -> *) where 
    type Null m :: k 
    type Mult m (i :: k) (j :: k) :: k 

    nullIx :: m (Null m) 
    multIx :: m i -> m j -> m (Mult m i j) 

class MonoidIx2 (m :: k -> l -> *) where 
    type Null1 m :: k 
    type Null2 m :: l 
    type Mult1 m (i :: k) (j :: k) :: k 
    type Mult2 m (p :: l) (q :: l) :: l 

    null1Ix :: m (Null1 m) p 
    null2Ix :: m i (Null2 m) 
    mult1Ix :: m i p -> m j p -> m (Mult1 m i j) p 
    mult2Ix :: m i p -> m i q -> m i (Mult2 m p q) 

Vous vous attendez un tas de lois (identité, associativité, commutativité lorsque vous mettez 4 blocs ensemble). Un exemple trivial d'un Monoid indexé: celui où l'indice n'a pas d'importance:

newtype Dummy (m :: *) (i :: k) = Dummy { getDummy :: m } 

instance Monoid m => MonoidIx (Dummy m :: * -> *) where 
    type Null (Dummy m)  =() 
    type Mult (Dummy m) i j =() 

    nullIx = Dummy mempty 
    multIx (Dummy i) (Dummy j) = Dummy $ mappend i j 

Je vais vous laisser mettre en œuvre l'instance pour les matrices;)

+0

Vraiment adore cette solution! Mais en fait, je pense que c'est trop pour le problème auquel je suis confronté. Merci beaucoup :) –