Haskell中的Monadic列表理解

 孙一诺她爹_480 发布于 2023-02-08 17:34

列表理解很容易理解.请看h以下定义.它使用pure_xs类型[Int]pure_f类型Int -> String,在列表推导中使用两者.

pure_xs :: [Int]
pure_xs = [1,2,3]

pure_f :: Int -> String
pure_f a = show a

h :: [(Int,Char)]
h = [(a,b) | a <- pure_xs, b <- pure_f a]
-- h => [(4,'4'),(5,'5'),(6,'6')]

大.现在采取两个略有不同的表达,monadic_f并且monadic_xs.我想g使用列表推导构建,看起来尽可能相似h.我有一种感觉,解决方案将涉及生成一系列IO操作,并使用sequence生成[(Int,Char)]IO monad 中的类型列表.

monadic_xs :: IO [Int]
monadic_xs = return [1,2,3]

monadic_f :: Int -> IO String
monadic_f a = return (show a)

g :: IO [(Int,Char)]
g = undefined -- how to make `g` function look
              -- as similar to `h` function as possible, i.e. using list comprehension?
-- g => IO [(4,'4'),(5,'5'),(6,'6')]

J. Abrahamso.. 10

写这个的自然方式是

do xs <- monadic_xs
   ys <- mapM monadic_f xs
   return (zip xs ys)

但是我们无法将其自然地转换为列表理解,因为我们需要(>>=)在那里绑定以提取monadic值.Monad变形金刚将是交织这些效果的途径.让我们来看看transformers ListTmonad变压器 - 即使它实际上并不是monad变压器.

newtype ListT m a = ListT { runListT :: m [a] }

listT_xs :: ListT IO Int
listT_xs = ListT monadic_xs

listT_f :: Int -> ListT IO String
liftT_f = ListT . fmap return . monadic_f

>>> runListT $ do { x <- listT_xs; str <- listT_f x; return (x, str) }
[(1,"1"),(2,"2"),(3,"3")]

所以这似乎工作,我们可以打开MonadComprehensions以列表理解格式编写它.

>>> runListT [ (x, str) | x <- listT_xs, str <- listT_f x ]
[(1,"1"),(2,"2"),(3,"3")]

这与我能想到的纯版本的结果类似,但它有一些危险的缺陷.首先,我们使用的ListT可能是不直观的,因为它打破了monad变换器定律,其次,我们只使用列表monadic效应的一小部分---通常列表将采用笛卡尔积,而不是zip .

listT_g :: Int -> ListT IO String
listT_g = ListT . fmap (replicate 3) . monadic_f

>>> runListT [ (x, str) | x <- listT_xs, str <- listT_g x ]
[(1,"1"),(1,"1"),(1,"1"),(2,"2"),(2,"2"),(2,"2"),(3,"3"),(3,"3"),(3,"3")]

要解决这些问题,您可能需要进行试验pipes.你会在那里得到"正确的"解决方案,尽管它看起来不像列表理解那么多.

1 个回答
  • 写这个的自然方式是

    do xs <- monadic_xs
       ys <- mapM monadic_f xs
       return (zip xs ys)
    

    但是我们无法将其自然地转换为列表理解,因为我们需要(>>=)在那里绑定以提取monadic值.Monad变形金刚将是交织这些效果的途径.让我们来看看transformers ListTmonad变压器 - 即使它实际上并不是monad变压器.

    newtype ListT m a = ListT { runListT :: m [a] }
    
    listT_xs :: ListT IO Int
    listT_xs = ListT monadic_xs
    
    listT_f :: Int -> ListT IO String
    liftT_f = ListT . fmap return . monadic_f
    
    >>> runListT $ do { x <- listT_xs; str <- listT_f x; return (x, str) }
    [(1,"1"),(2,"2"),(3,"3")]
    

    所以这似乎工作,我们可以打开MonadComprehensions以列表理解格式编写它.

    >>> runListT [ (x, str) | x <- listT_xs, str <- listT_f x ]
    [(1,"1"),(2,"2"),(3,"3")]
    

    这与我能想到的纯版本的结果类似,但它有一些危险的缺陷.首先,我们使用的ListT可能是不直观的,因为它打破了monad变换器定律,其次,我们只使用列表monadic效应的一小部分---通常列表将采用笛卡尔积,而不是zip .

    listT_g :: Int -> ListT IO String
    listT_g = ListT . fmap (replicate 3) . monadic_f
    
    >>> runListT [ (x, str) | x <- listT_xs, str <- listT_g x ]
    [(1,"1"),(1,"1"),(1,"1"),(2,"2"),(2,"2"),(2,"2"),(3,"3"),(3,"3"),(3,"3")]
    

    要解决这些问题,您可能需要进行试验pipes.你会在那里得到"正确的"解决方案,尽管它看起来不像列表理解那么多.

    2023-02-08 17:37 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有