2017-06-25 3 views
1

J'apprends la programmation fonctionnelle en utilisant le langage Scala. J'ai lu le tutoriel sur le foncteur que le foncteur a 2 lois:Scala: exemple de compteur de loi de composition

1. identity law: functor.map(x => x) ≡ functor 
2. Composition law: functor.map(x => f(g(x))) ≡ functor.map(g).map(f) 

La chose que je ne connais pas la loi de composition. J'ai le sentiment que toute fonction a cette propriété: f (g (x)) = functor.map (g) .map (f). Pouvons-nous avoir un exemple qui n'obéisse pas à cette règle?

Merci

+0

Ce que vous appelez « loi de composition "s'appelle en fait" Associativity Law ": https://en.wikipedia.org/wiki/Functor#Definition. Il y a beaucoup d'instances de foncteurs, mais une seule qui satisfait ce 'f (g (x)) = functor.map (g) .map (f)' donc ce n'est pas une propriété inhérente aux foncteurs. – pedrofurla

+1

Je crois que "la loi de composition" est correcte. Cela semble cohérent avec l'article Wikipédia que vous avez lié. –

+1

@pedrofurla [Lois de l'associativité] (https://en.wikipedia.org/wiki/Associative_property#Definition) impliquent trois éléments et prennent généralement la forme 'x <> (y <> z) = (x <> y) < > z' (où l'opération associative est appelée '<>' ici). Ou, en évitant l'infixe, ce serait 'h (x, h (y, z)) = h (h (x, y), z)'. La loi de composition des foncteurs signifie qu'un foncteur est une sorte d '[homomorphisme] (https://en.wikipedia.org/wiki/Homomorphism#Definition) (entre catégories). Je crois que "loi de composition" est un terme assez raisonnable (puisque l'homomorphisme est sur l'opération de composition). –

Répondre

1

Voici un exemple de la façon dont Set viole la 2ème loi de foncteur (et est donc pas un foncteur, même si au début il peut sembler un):

case class Foo(s: String) { 
    override def equals(obj: scala.Any): Boolean = obj match { 
    case Foo(t) => s.toUpperCase == t.toUpperCase 
    case _ => false 
    } 
} 

val toFoo = (s: String) => Foo(s) 
val fromFoo = (foo: Foo) => foo.s 

val set = Set("something", "SOMETHING") 

set.map(toFoo).map(fromFoo)  // Set(something) 
set.map(x => fromFoo(toFoo(x))) // Set(something, SOMETHING) 
+0

Il convient de noter que cela n'est possible que parce que Scala vous permet de violer les lois de logique avec l'égalité définie par l'utilisateur. Une fois que vous autorisez l'égalité qui n'obéit pas 'forall f. x == y implique f (x) == f (y) 'vous libérez toutes sortes de démons. –

+0

L'équation à laquelle vous faites référence est cependant respectée. Pour deux chaînes 'a' et' b' égales, 'Foo (a)' et 'Foo (b)' sont égaux. Rompre la loi logique serait dire qu'il y a des cas où pour deux entrées identiques, nous obtenons deux résultats différents, mais ce n'est pas le cas. Je viole 'forall f. f (x) == f (y) implique x == y' et c'est bien (toute surjection viole cela, prenez 'List.length' par exemple). – slouc

+0

a == b n'implique pas deFoo (a) == fromFoo (b) et c'est ce qui casse la logique. –