haskell - 用于在元组中构建列表的有状态递归
问题描述
我将下面的示例代码放在一起来演示我的问题:什么是在元组中构建列表的递归方式?
我想改变recommendNPages
它recommendPage
以递归方式调用返回([Post], Blog)
,而不是利用Blog
's 数据构造函数。
data Tag = Food | Tech | Business | Travel | None
deriving (Show, Read, Eq, Ord, Bounded, Enum)
data Author = Joe | Bob | Kayla | Jade
deriving (Show, Read, Eq, Ord, Bounded, Enum)
data Post = Post{getRank::Tag,getAuthor::Author}
deriving (Eq,Ord)
instance Show Post where
show (Post t a) = "Tag: " ++ (show t) ++ " - " ++ "Author: "++ (show a)
newtype Blog = Blog [Post]
instance Show Blog where
show (Blog posts) = "This blog has " ++ (show (length posts)) ++" posts"
fullBlog :: Blog
fullBlog = Blog [Post t a | a <- [Joe .. Jade],
t <- [Food .. None]]
recommendPage :: Blog -> (Post,Blog)
recommendPage (Blog posts) = (head posts,Blog (tail posts))
recommendNPages :: Int -> Blog -> ([Post], Blog)
recommendNPages n (Blog posts) = (take n posts, Blog $ drop n posts)
任何建议或文档链接将不胜感激。
解决方案
有几点需要注意。首先,您的recommendPage
函数是不安全的,因为它在空列表上失败。最好避免使用 和 之类的函数head
,tail
这些函数不是全部并且在某些输入上失败。其次,从逻辑上讲,将您的recommendNPages
功能作为“主要”功能似乎更自然,然后实现recommendPage
为recommendNPages 1
.
但我会假设你有充分的理由去做你想做的事情。然后你可以使用这个简单的实现:
recommendNPages :: Int -> Blog -> ([Post], Blog)
recommendNPages 0 blog = ([], blog)
recommendNPages n blog =
case recommendPage blog of
(post, blog') -> case recommendNPages (n - 1) blog' of
(posts, blog'') -> (post : posts, blog'')
但是,每当您看到这种模式时,您都应该怀疑涉及到一个状态,您确实这样做了,从问题标题中的“有状态”一词来判断:)。
事实上,您可以将您的recommendPage
函数视为一个有状态计算,通过从中提取一个页面来“修改”博客,然后您recommendNPages
就变成了重复n
多次的这种状态计算。
我们在 Haskell 中用于这种计算的工具称为State
monad。结合replicateM
迭代一元计算n
时间的函数,我们得到:
recommendNPages :: Int -> Blog -> ([Post], Blog)
recommendNPages n = runState $ replicateM n step
where
-- | One step of our computation. (Just wrapping it into `State`.)
step :: State Blog Post
step = state recommendPage
推荐阅读
- c - scanf 子进程后的垃圾值
- asp.net-mvc - 运行从github下载的项目
- sql-server - 启动SSIS包时不支持包部分调试
- r - 如何减少 geom_text 标签之间的空间?
- powerbi - Power Bi DAX:重置某个日期之后的值
- java - 如何将动态元数据添加到 Java 中的单例 SLF4J 记录器?
- replace - 读取文本文件中的内容并使用 VBS 将其替换为另一个文本文件中的指定文本
- vb.net - Xamarin iOS Webview 自动执行 OnClientClick()
- python - Jupyter 笔记本安装失败
- javascript - 如何配置 webpack 以将自定义字体加载到故事书中?