Обратите внимание, что каждый шаг loop
выполняет две вещи одновременно: они (возможно) генерируют действие печати из каждого элемента списка, а затем объединяют это действие с оставшимися (используя (>>)
). Если вы хотите написать loop
в терминах map
, вам необходимо отключить эти два подэтапа. Например, вы можете определить функцию ...
printDiffIfAboveAvg :: Double -> IO()
..., а затем применить его ко всем элементам списка с map printDiffIfAboveAvg
. Это даст вам список действий, типа [IO()]
, что вам нужно будет объединить в одно общее действие:
runAllActions :: [IO()] -> IO()
runAllActions
уже существует в базовой библиотеке, в более общей версии под названием sequence_
:
sequence_ :: (Foldable t, Monad m) => t (m a) -> m()
Итак, у вас было бы loop = sequence_ . map printDiffIfAboveAvg
. На самом деле, есть и другая функция в базовой библиотеке ...
mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m()
... который выполняет именно эту комбинацию sequence_
и map
.
Хорошим правилом, чтобы жить, является, как можно больший, из вашего чистого кода. В этом духе я бы написал «mapM_ print». foo где foo = map (вычесть среднее значение). фильтр (> средний) '. Это действительно помогает писать типы вещей, которые вы уже написали, а также типы вещей, которые вы хотите написать: поэтому вы говорите, что хотите использовать «карту», то какой тип функции вы намереваетесь перейти на 'map'? Не похоже, что вы думали, что далеко впереди – jberryman