Я читаю книгу Конора Макбрайда и Росса Патерсона "Функциональная жемчужина / идиомы: прикладное программирование с эффектами:" ( новая версия с "идиомами" в названии).У меня небольшие трудности с Упражнением 4, которое объясняется ниже.Любые подсказки будут высоко оценены (особенно: я должен начать писать fmap
и join
или return
и >>=
?).
Постановка проблемы
Вы хотите создатьinstance Monad []
, где
return x = repeat x
и ap = zapp
.
Стандартные библиотечные функции
Как на стр.2 статьи, ap
применяет монадическое значение-функцию к монадическому значению.
ap :: Monad m => m (s -> t) -> m s -> m t
ap mf ms = do
f <- mf
s <- ms
return (f s)
Я расширил это в канонической записи до,
ap mf ms = mf >>= (\f -> (ms >>= \s -> return (f s)))
Функция, зависящая от спискаzapp
(«приложение zippy») применяет функцию из одного списка к соответствующему значению в другом, а именно:
zapp (f:fs) (s:ss) = f s : zapp fs ss
Мои трудности
Обратите внимание, что в развернутом виде mf :: m (a -> b)
это список функций [(a -> b)]
в нашем случае.Итак, в первом приложении >>=
мы имеем
(f:fs) >>= mu
, где mu = (\f -> (ms >>= \s -> return (f s)))
.Теперь мы можем вызвать fs >>= mu
в качестве подпрограммы, но это не знает, как удалить первый элемент ms
.(Напомним, что мы хотим, чтобы результирующий список был [f1 s1, f2 s2, ...]. Я пытался что-то взломать, но ... как и предполагалось, это не сработало ... любая помощь будет высоко оценена.
Заранее спасибо!
Редактировать 1
Я думаю, что я заставил его работать, сначала я переписал ap
с fmap
и join
как пользователь "comonad"предложил.
Мой прыжок веры предполагал, что fmap = map
. Если кто-нибудь может объяснить, как туда добраться, я был бы очень признателен. После этого ясно, что join
работает в спискеперечисляет предложенную пользователем "comonad" и должна быть диагональю \x -> zipWith ((!!) . unL) x [0..]
. Мой полный код такой:
newtype L a = L [a] deriving (Eq, Show, Ord)
unL (L lst) = lst
liftL :: ([a] -> [b]) -> L a -> L b
liftL f = L . f . unL
joinL :: L (L a) -> L a
joinL = liftL $ \x -> zipWith ((!!) . unL) x [0..]
instance Functor L where
fmap f = liftL (map f)
instance Monad L where
return x = L $ repeat x
m >>= g = joinL (fmap g m)
надеюсь, это правильно (похоже, это "решение" на стр. 18 статьи) ... спасибо за помощь всем!