Так что есть функция в Haskell, что я упростил с целью задать этот вопрос:Подъемные функции с другой функцией в качестве аргумента в Haskell
import Data.Foldable
import Data.Set
myFn :: Int -> Set Int
myFn a
| a <= 0 = singleton 1
| otherwise = foldMap helper (myFn (a - 1))
helper :: Int -> Set Int
helper a = insert (a + 2) (singleton a)
main :: IO()
main = print . Data.Set.toList $ myFn 5
Я хочу иметь myFn
«ю.ш. зависимость от helper
быть положенным в Reader
, так как инверсия управления позволяет мне переключаться реализации в моих тестах:
import Control.Monad.Reader
import Data.Foldable
import Data.Set
data MyEnv = MyEnv { helper' :: Int -> Set Int }
type MyReader = Reader MyEnv
myFn :: Int -> MyReader (Set Int)
myFn a
| a <= 0 = return $ singleton 1
| otherwise = do
myFn' <- myFn (a - 1)
helper'' <- asks helper'
return (foldMap helper'' myFn')
helper :: Int -> Set Int
helper a = insert (a + 2) (singleton a)
main :: IO()
main =
let
myEnv = MyEnv helper
in
print . Data.Set.toList $ runReader (myFn 5) myEnv
Это работает отлично, за исключением того, я не люблю эти три линии, в частности:
myFn' <- myFn (a - 1)
helper'' <- asks helper'
return (foldMap helper'' myFn')
Я чувствую, что должен быть способ поднять foldMap
таким же образом, как mapM
является поднятая версия map
по своему составу с sequence
. В идеале я хотел бы эти три линии, чтобы свернуть вниз к одному:
foldMapM helper'' (partitions (n - 1))
Предполагая, что: helper'' :: Int -> MyReader (Set Int)
Это, конечно, потребует foldMapM
функции с подписью аналогичной:
foldMapM
:: (Monad m, Foldable t, Monoid n)
=> (a -> m n)
-> m (t a)
-> m n
Я пробовал так много всего, но я просто не могу реализовать эту функцию! Может ли кто-нибудь помочь?
На самом деле, 'foldMapM f xs = liftM2 foldMap f xs' имеет подпись' foldMapM :: (Monad m, Foldable t, Monoid n) => m (a -> n) -> m (ta) -> mn' , Я пробовал это безуспешно раньше, так как моя функция была типа '(a -> m n)'. Я не думал, что нужно сделать 'asks helper'' inline, чтобы получить' m (a -> n) '. Это потрясающе! – arussell84