Możemy zrobić trochę rozumowania równania. Najpierw spójrzmy na bar'
. Napiszę go w tej formie
asks bar >>= \z -> return (z i)
Okazuje się, że liftM
określa się liftM f m = m >>= \a -> return (f a)
który pasuje do wzorca wyżej. Warto więc zastąpić go
liftM ($ i) (asks bar)
Następnie mamy foo
jako
liftM show (liftM ($ i) (asks bar))
Albo rozpisane trochę szczególnie
liftM show . liftM ($ i) $ asks bar
Jeśli wiemy, że liftM
jest fmap
możemy rozpoznać Functor
prawo tutaj odtwarzane
fmap show . fmap ($ i) $ asks bar -- equals
fmap (show . ($ i)) $ asks bar
nie jestem osobiście wielkim fanem używając ($ i)
jako funkcja, więc niech przepisać go jako wyraźnej lambda
fmap (\f -> show (f i)) (asks bar)
Teraz, możemy zdecydować się wyeliminować asks
za pomocą bar
w miejscu połączenia (to znaczy używać bar
w zależności od rodzaju bar :: FooEnv -> Int -> Int
fmap (\f -> show (bar f i)) ask
i jako ostatni trik, możemy użyć flip
iść sensu w funkcji fmap
ped a nawet zwrotu wykorzystanie asks
(dzięki Ørjan Johansen)
fmap (show . flip bar i) ask -- or even
show . flip bar i <$> ask -- or even
asks (show . flip bar i)
Nie mówię, że jest to najbardziej czytelny lub wspaniały sposób wykonania tego zadania, ale można zobaczyć, jak możemy po prostu zredukować elementy za pomocą równania rozumowania.
Zauważ, że 'prosi f' jest równoważne' f <$> ask', więc zależnie od twojego gustu możesz go ponownie wprowadzić na końcu: 'pyta $ show. flip bar i' –
Dzięki, @ j-abrahamson! Szczegółowe czynności są bardzo pomocne. Powinienem być bardziej konkretny, ponieważ nie chcę wstawiać 'bar'' do' foo'. Postaram się jednak zrozumieć kroki, które podjąłeś, aby móc spróbować stworzyć bezbłędną wersję 'bar''. Wolę "prosi" o "ask", więc dziękuję również, @ Ørjan-johansen, za dodanie tego ostatniego kroku. – arussell84
Rozgryzłem to: 'bar 'i' = pyta $ flip bar i'' lub' bar '= pyta. odwróć pasek " – arussell84