2015-09-30 13 views
14

Ich spielte herum mit einer einfachen Funktion für jemand anderes Stack-Überlauf Frage, und schrieb den Ausdruck (mit Applicative ((>) t), vielleicht?):Vervielfältigung ausbauen -

f a x ++ f a y 

Offensichtlich ist dies die Der beste Weg, um diesen Ausdruck im wirklichen Leben zu schreiben, vorausgesetzt, ich habe sowieso alle diese Variablen im Umfang, aber ich sah die Verdoppelung von f a, und dachte "Hey, vielleicht können Sie das mit der Applicative Instanz für Funktionen entfernen". Ich beendete mit:

liftA2 (++) (flip f x) (flip f y) a 

was einfach schrecklich ist. Gibt es eine bessere Möglichkeit, diese Duplizierung zu entfernen? Offensichtlich konnte ich die Duplizierung auch entfernen, indem Sie f a an etwas in einer where-Klausel binden, aber das war als eine Übung bei der Verwendung von integrierten Funktionen gedacht.

Antwort

21

könnten Sie

tun
((++) `on` f a) x y 

Das ist nicht Applicative nicht verwendet, aber (leider).

+0

ich diese Antwort mögen, obwohl! Ich glaube, ich suchte nicht wirklich nach anwendungsspezifischen Antworten, sondern nach Möglichkeiten, die Standardbibliothek zu verwenden, um die Duplizierung zu entfernen. – amalloy

21

[...] vielleicht können Sie das mit der Applicative-Instanz für Funktionen entfernen.

Müssen Sie die Applicative Instanz von ((->) t) verwenden? Wenn Sie nur die doppelte f a loswerden wollen, warum nicht stattdessen die Liste Monade verwenden?

[x, y] >>= f a 

oder äquivalent

f a =<< [x, y] 

Beispiel:

λ> let f :: Int -> Int -> [Int]; f a x = [a .. x] 

λ> f 1 2 ++ f 1 3 
[1,2,1,2,3] 

λ> [2, 3] >>= f 1 
[1,2,1,2,3] 

λ> f 1 =<< [2, 3] 
[1,2,1,2,3] 
+0

Es ist erwähnenswert, dass '= <<' in dieser Situation das gleiche wie 'concatMap' ist. Wenn Sie also über Listenmanipulationen statt über Monaden nachdenken möchten, ist das die zu verwendende Funktion. –

+0

@ cool_me5000 Sicher, aber ich wollte den monadischen Aspekt der Operation betonen. – Jubobs

14

Bikeshedding macht Spaß! Eine andere Möglichkeit wäre es, die Monoid Instanz für Funktionen zu verwenden:

(($x) <> ($y)) (f a) 
+1

Ich verstehe das nicht. Ist 'Mappend'-Komposition nicht für Funktionen? Und was ist mit dem '++' passiert? – amalloy

+0

@amalloy Für Funktionen ist 'mappend' punktweise angehängt:' mappend f g x = mappend (f x) (g x) '. Das '(++)' verschwindet, weil es der 'mappend' ist, der an jedem Punkt passiert. –

3

Da die Frage zu einer Lösung angedeutet mit Applicative (obwohl andere Antworten sind elegantere) ...

((++) <$> ($ x) <*> ($ y)) (f a) 
+0

Wenn Sie einige Klammern loswerden wollen, können Sie schreiben: '(++) <$> ($ x) <*> ($ y) $ f a'. – Jubobs

+1

@Jubobs Ich bin mir nicht sicher, ob er Recht hat oder nicht, aber ich habe mich entschieden, Gabriel Gonzalez 'Ratschlag zu überprüfen, wie man Haskell-Code für Nicht-Haskeller lesbarer machen kann: http://www.haskellforall.com/2015/09 /how-to-make-your-haskell-code-more.html. '($)' Zu vermeiden, ist seine beste Empfehlung. – frasertweedale

+0

Danke für den Link ':)' – Jubobs

Verwandte Themen