userei il fatto che è possibile convertire facilmente un Bool
a un Int
utilizzando fromEnum
:
addif x acc y = acc + fromEnum (x == y)
Ora è possibile iniziare ad applicare i soliti trucchi per renderlo punto-libera
-- 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
E così via. Non toglierò tutto il divertimento di renderlo punto libero, specialmente quando ci sono strumenti per farlo per te.
In alternativa, si potrebbe scrivere una funzione come
count x = sum . map (fromEnum . (==) x)
che è quasi Point gratuito, e ci sono trucchi che ci si avvicina, anche se ottengono piuttosto brutta in fretta:
count = fmap fmap fmap sum map . fmap fmap fmap fromEnum (==)
Here I pensa che in realtà sembra più bello usare fmap
anziché (.)
, anche se è possibile sostituire ogni fmap
con (.)
e sarebbe lo stesso codice esatto.In sostanza, il (fmap fmap fmap)
compone un singolo argomento e una funzione a due argomenti insieme, se invece dà il nome .:
si potrebbe scrivere questo come
count = (sum .: map) . (fromEnum .: (==))
Ripartiti:
> :t fmap fmap fmap sum map
Num a => (a -> b) -> [a] -> b
quindi ci vuole una funzione da b
a un numero a
, un elenco di b
s e restituisce un a
, non troppo male.
> :t fmap fmap fmap fromEnum (==)
Eq a => a -> a -> Int
E questo tipo può essere scritto come Eq a => a -> (a -> Int)
, che è una cosa importante da notare. Questo rende il tipo di ritorno di questa funzione corrispondente all'ingresso a fmap fmap fmap sum map
con b ~ Int
, quindi possiamo comporli per ottenere una funzione di tipo Eq a => a -> [a] -> Int
.
è possibile eseguire math-chenigans come 'let fxy = 1 - ceiling (fromIntegral (xy)/fromIntegral y) :: Int'? (che non è esattamente quello che ti serve;)) – Carsten
ma '1 - ceiling (abs $ fromIntegral (xy)/fromIntegral (max xy)) :: Int' dovrebbe farlo se non mi mancassi qualche brutto caso di confine da qualche parte - forse vorrete ragionarci sopra o eseguire alcuni quickchecks;) (beh, mi mancano alcuni negativi quindi dovrete avere più addominali in ... ma il principio dovrebbe essere ovvio ... la vera soluzione è * banale * e sinistra per il lettore **: D **) – Carsten
In generale è possibile sostituire un'istruzione 'if' con la funzione' bool :: Bool -> a -> a -> a; bool False f _ = f; bool True _t = t', nel qual caso puoi sempre formare un'espressione "normale" che può essere resa punto libero con i metodi regolari. – user2407038