Zastanawiałem się, jak napisać f x = zip x (tail x)
w punkcie wolnym. Użyłem programu pointfree, a wynikiem było f = ap zip tail
. ap
funkcja od Control.MonadJak działa wyrażenie `ap zip tail`?
Nie rozumiem, jak działa punktowa definicja. Mam nadzieję, że uda mi się to rozgryźć, jeśli potrafię to zrozumieć z perspektywy typów.
import Control.Monad (ap)
let f = ap zip tail
let g = ap zip
:info ap zip tail f g
ap :: Monad m => m (a -> b) -> m a -> m b
-- Defined in `Control.Monad'
zip :: [a] -> [b] -> [(a, b)] -- Defined in `GHC.List'
tail :: [a] -> [a] -- Defined in `GHC.List'
f :: [b] -> [(b, b)] -- Defined at <interactive>:3:5
g :: ([a] -> [b]) -> [a] -> [(a, b)]
-- Defined at <interactive>:4:5
Patrząc na wypowiedzi ap zip tail
Myślę, że zamek błyskawiczny jest pierwszym parametrem ap
i ogona jest drugim parametrem ap
.
Monad m => m (a -> b) -> m a -> m b
\--------/ \---/
zip tail
Ale nie jest to możliwe, ponieważ rodzaje zip
i tail
są zupełnie inne niż to, co funkcja ap
wymaga. Nawet biorąc pod uwagę, że lista jest monadą.
Jedyne, co mogę wymyślić, to że 'a' w typie ap staje się' [a] -> [b] 'typem zip. Jeśli tak jest, to jakie są zasady unifikacji (jeśli to właściwe słowo), które to rządzą? – user7610
ghci mówi, że typ to 'ap zip tail :: Monad ((->) [b]) => [b] -> [(b, b)]' ... bez zbytniego śledztwa, powiedziałbym 'Monad ((->) [b])' jest tym, co chcesz przeczytać. Myślę, że http://learnyouahaskell.com/for-a-few-monads-more#reader pomoże ci zrozumieć, co się tutaj dzieje. –
Nawiasem mówiąc, 'zip <*> tail' jest równoważny i ładniej wygląda – jozefg