würde ich die Tatsache nutzen, dass man leicht ein Bool
auf ein Int
mit fromEnum
umwandeln kann:
addif x acc y = acc + fromEnum (x == y)
Nun können Sie die üblichen Tricks anwenden, um es frei Punkt-
-- Go prefix and use $
addif x acc y = (+) acc $ fromEnum $ (==) x y
-- Swap $ for . when dropping the last argument
addif x acc = (+) acc . fromEnum . (==) x
Und so weiter. Ich werde nicht den ganzen Spaß davon nehmen, es frei zu machen, besonders wenn es Werkzeuge gibt, die es für dich tun.
Alternativ könnten Sie eine Funktion wie
count x = sum . map (fromEnum . (==) x)
schreiben, die fast frei ist Punkt, und es gibt Tricks, die Sie näher kommen, obwohl sie schnell ziemlich böse bekommen:
count = fmap fmap fmap sum map . fmap fmap fmap fromEnum (==)
Here I denke, es sieht tatsächlich schöner aus, fmap
anstelle von (.)
zu verwenden, obwohl Sie alle fmap
durch (.)
ersetzen könnten und es genau derselbe Code wäre.Im Wesentlichen komponiert die (fmap fmap fmap)
ein einziges Argument und zwei zusammen Argument Funktion, wenn Sie den Namen stattdessen geben .:
Sie dies als
count = (sum .: map) . (fromEnum .: (==))
Gegliedert schreiben konnte:
> :t fmap fmap fmap sum map
Num a => (a -> b) -> [a] -> b
So dauert es eine Funktion von b
zu einem numerischen a
, eine Liste von b
s, und gibt eine a
zurück, nicht so schlecht.
> :t fmap fmap fmap fromEnum (==)
Eq a => a -> a -> Int
Und diese Art kann als Eq a => a -> (a -> Int)
geschrieben werden, was eine wichtige Sache zu beachten ist. Das macht den Rückgabetyp dieser Funktion mit der Eingabe fmap fmap fmap sum map
mit b ~ Int
übereinstimmt, so dass wir sie zusammensetzen können, um eine Funktion des Typs Eq a => a -> [a] -> Int
zu erhalten.
darf man Mathe-chenigans wie 'let fxy = 1 - ceiling (fromIntegral (xy)/fromIntegral y) :: Int'? (was nicht genau das ist, was du brauchst;)) – Carsten
aber '1 - ceiling (abs $ fromIntegral (xy)/fromIntegral (max xy)) :: Int' sollte es tun, wenn ich irgendwo einen fiesen Grenzfall nicht vermisse - vielleicht Du wirst darüber nachdenken oder ein paar Quickchecks machen;) (Nun, ich habe ein paar Negative vermisst, also musst du doch mehr "abs" haben ... aber das Prinzip sollte offensichtlich sein ... die wirkliche Lösung ist * trivial * und links für den Leser **: D **) – Carsten
Im Allgemeinen können Sie eine 'if'-Anweisung durch die Funktion' bool :: Bool -> a -> a -> a; bool Falsch f _ = f; bool True _ t = t', in diesem Fall können Sie immer einen "normalen" Ausdruck bilden, der mit den regulären Methoden point-free gemacht werden kann. – user2407038