Функция bind
(>>=
) имеет сигнатуру:
m a -> (a -> m b) -> m b
Однако мне нужна функция с подписью:
m (t a) -> (a -> m (t b)) -> m (t b)
В частности, у меня есть функция, которая, учитывая целое число, возвращает список целых чисел внутри IO:
f :: Int -> IO [Int]
но я хочу применить его к IO of list of Integers
, и я не могу использовать обычную функцию привязки, потому что она заключена в два контейнера, то есть список, содержащийся в IO. Поиск в hoogle не помогает.
Я использую следующий подход для реализации этого:
Допустим, реализация функции такова:
f :: Int -> IO [Int]
f x = do
return $ [x-10, x+10]
Я использую две вспомогательные функции, чтобы получить то, что я хочу:
f' :: [Int] -> IO [Int]
f' xs = do
list <- traverse f xs
return $ join list
f'' :: IO [Int] -> IO [Int]
f'' xs = do
ys <- xs
f' ys
Вышеизложенное работает, но я хотел бы знать, есть ли лучший/идиоматический способ реализовать это в haskell?
f'
иf''
и абстрагируетеf
в параметр, вы получите наиболее общий тип, выведенный средством проверки типов. Я бы сказал, что эти реализации идиоматичны, за исключением, возможно, использования нотацииdo
вместо>>=
иfmap
, но это чисто стилистические проблемы. В нынешнем виде этот вопрос полностью основан на мнении - можете ли вы уточнить, что в вашем коде недостаточно хорошо, то есть чего вы хотели бы добиться в «лучшей» версии? - person user2407038   schedule 05.08.2017