Как я должен вызвать эту функцию? Мне нужна функция, которая возвращает кортеж

#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. Большое спасибо! У меня еще не было монад в моем исследовании, и поэтому у меня были проблемы с этим. Еще раз спасибо.