2012-06-07 9 views
9

Próbowałem przekonwertować przykład haskell, natknąłem się wcześniej, na scalaz. Oryginalny przykładem było to:Aplikacja instancji dla krotki z monoidem i funkcją wewnątrz

("Answer to the ", (*)) <*> ("Ultimate Question of ", 6) <*> ("Life, the Universe, and Everything", 7) 

które, o ile jestem w stanie zrozumieć, wykorzystuje this instancji.

To nie zostanie przekształcony do scalaz dosłownie:

scala> ("Answer to the ", ((_: Int) * (_: Int)) curried) |@| ("Ultimate Question of ", 6) |@| ("Life, the Universe, and Everything", 7) tupled 
res37: (java.lang.String, (Int => (Int => Int), Int, Int)) = (Answer to the Ultimate Question of Life, the Universe, and Everything,(<function1>,6,7)) 

Mimo, szukałem na przykład, i wydaje be there (ponownie, o ile jestem w stanie zrozumieć).

Pytanie brzmi: dlaczego tak nie działa? A może przegapiłem/nie dostałem poprawnie?

+1

Ten kod rzeczywiście wysyła do instancji aplikacji dla krotek. Który z kolei używa monidalnego 'mappend' dla list (konkatentacja). Tak więc jest to skład funkcji drugiej części krotki, z konkatentacją listy pierwszej części. –

Odpowiedz

5

Scalaz's odpowiednik Control.Applicative 's <*> jest również nazywany <*>, chociaż myląco przyjmuje argumenty w odwrotnej kolejności. A zatem następujące utwory:

val times = ((_: Int) * (_: Int)) curried 
val a = "Answer to the " 
val b = "Ultimate Question of " 
val c = "Life, the Universe, and Everything" 

(c, 7) <*> ((b, 6) <*> (a, times)) 

Albo, jak już wspomniano w odpowiedzi na Twój komentarz, można użyć następujących jeśli chcesz trzymać |@|:

(a -> times |@| b -> 6 |@| c -> 7)(_ apply _ apply _) 

ja osobiście wolę <*> wersja, nawet jeśli czuje się do tyłu.


Możemy przejść przez to, co dzieje się w trochę bardziej szczegółowo. Przede wszystkim nie potrzebujesz pełnej mocy Applicative tutaj-Apply. możemy uzyskać instancji Apply za krotki używając implicitly:

scala> val ai = implicitly[Apply[({type λ[α]=(String, α)})#λ]] 
ai: scalaz.Apply[[α](java.lang.String, α)] = [email protected] 

Teraz możemy zastosować nasz pierwszy krotki do drugiego:

scala> :t ai(a -> times, b -> 6) 
(java.lang.String, Int => Int) 

a wynik do trzeciego:

scala> :t ai(ai(a -> times, b -> 6), c -> 7) 
(java.lang.String, Int) 

Czego chcemy:

scala> ai(ai(a -> times, b -> 6), c -> 7)._1 
res0: java.lang.String = Answer to the Ultimate Question of Life, the Universe, and Everything 

scala> ai(ai(a -> times, b -> 6), c -> 7)._2 
res1: Int = 42 

Metoda <*> na MA po prostu owija to nieco ładniej.

+0

Dzięki, działa tak, jak powinno. Przy okazji, czy masz jakiś pomysł, jak to zrobić z ApplicativeBuilder i czy będzie wyglądał lepiej w ten sposób? – folone

+1

Oczywiście, możesz zrobić coś takiego jak '(a -> razy | @ | b -> 6 | @ | c -> 7) (_ apply _ apply _)', ale myślę, że wersja '<*>' jest ładniejsza. –

+0

Tak, to działa. Byłem wprowadzony w błąd przez fakt, że "tupled" przykleił monoid, więc pomyślałem, że on również zastosuje tę funkcję. – folone

Powiązane problemy