#haskell
#haskell
Вопрос:
У меня есть одна проблема с этим кодом :
append (first, second) f = (first fst(f second), snd(f second))
^^^^^^^^^^^^^ ^^^^^^^^^^^^^
Я не знаю, как вызвать эту функцию, потому что я не понимаю, как правильно сопоставлять ^
функции с -marked . На мой взгляд, мне нужна функция, которая возвращает кортеж, потому что функция fst требует этого.
Комментарии:
1. Если моя правка изменила смысл вашего сообщения, не стесняйтесь отредактировать его заново.
2. Спасибо, я попробовал выделить эту функцию жирным шрифтом, но она не сработала.
3. Да, вы не можете использовать форматирование (жирный шрифт, курсив и т. Д.) Внутри блоков кода.
4. В любом случае, можете ли вы описать (словами), что именно вы хотите
append
, чтобы функция выполняла?5. Хорошо, какой тип
append
? Какие аргументы вы пытались передатьappend
? Какие функции вы пытались построить, чтобы соответствоватьappend
типам аргументов? В общем: что вы сделали, что вы ожидали, и что произошло вместо этого?
Ответ №1:
Если вы немного перепишете свое выражение с явным сопоставлением шаблонов и совместным использованием, все станет понятнее :
append :: ([w], a) -> (a -> ([w], b)) -> ([w], b)
append (w, a) f = let (w', b) = f a
in (w w', b)
Итак, вы берете кортеж со списком и значением, применяете функцию, создающую другой список. Список добавляется к исходному списку, а значение заменяет предыдущее в кортеже.
Похоже, вы заново изобрели ((,) w)
монаду, известную как монада писателя!
Посмотрите на тип >>=
(bind), он применяет функцию к момадическому значению, создавая другое монадическое значение :
(>>=) :: Monad m => m a -> (a -> m b) -> m b
Теперь, если вы замените m
на ((,) w)
(или (w,)
если обозначения для разделов кортежей были разрешены в типах), такие, что m a
стали (w, a)
, вы получите :
bindSpecialized :: (w, a) -> (a -> (w, b)) -> (w, b)
Однако ((,) w)
может использоваться только как монада, если у нас есть способ объединить w
s. Вы достигли этого с помощью списков и
. Более общий подход заключается в использовании класса type Monoid
для type с ассоциативной операцией и элементом identity .
По некоторым причинам, ((,) w)
не является монадой, определенной в прелюдии, рекомендуется использовать newtype:
newtype Writer w a = Writer { runWriter :: (w, a) }
instance Functor (Writer w) where
fmap f (Writer (w, a)) = Writer (w, f a)
instance Monoid w => Monad (Writer w) where
return a = Writer (mempty, a)
(Writer (w, a)) >>= f = let Writer (w', b) = f a
in Writer (w <> w', b)
tell :: Monoid w => w -> Writer w ()
tell w = Writer (w, ())
-- test == ("hello world", 3)
test :: (String, Int)
test = runWriter $ do
a <- test1
b <- test2
return $ a b
where
test1 = tell "hello" >> return 1
test2 = tell " world" >> return 2
Для практических программ вы должны использовать Writer
тип и его экземпляр монады, уже определенные в Control.Monad.Trans.Writer
.
Комментарии:
1. Большое спасибо! У меня еще не было монад в моем исследовании, и поэтому у меня были проблемы с этим. Еще раз спасибо.