首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Haskell中实现List#flatten

在Haskell中实现List#flatten
EN

Stack Overflow用户
提问于 2015-01-05 05:15:30
回答 3查看 512关注 0票数 5

Scala提供了一个List#flatten方法,用于从List[Option[A]]List[A]

代码语言:javascript
复制
scala> val list = List(Some(10), None)
list: List[Option[Int]] = List(Some(10), None)

scala> list.flatten
res11: List[Int] = List(10)

我试图在Haskell中实现它:

代码语言:javascript
复制
flatten :: [Maybe a] -> [a]
flatten xs = map g $ xs >>= f

f :: Maybe a -> [Maybe a]
f x = case x of Just _  -> [x]
                Nothing -> []

-- partial function!
g :: Maybe a -> a
g (Just x) = x

然而,我不喜欢g是一个部分函数,即非完全函数。

是否有一种完全方法来编写这样的flatten函数?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-01-05 05:26:48

您的flattencatMaybes (链接)相同,定义如下:

代码语言:javascript
复制
catMaybes :: [Maybe a] -> [a]
catMaybes ls = [x | Just x <- ls]

列表理解中的特殊语法Just x <- ls意味着从ls中提取一个元素,如果它不是Just,则放弃它。否则,通过模式分配x,将值与Just x匹配。

票数 11
EN

Stack Overflow用户

发布于 2015-01-05 22:41:01

只要稍微修改一下代码,就可以做到这一点:

代码语言:javascript
复制
flatten :: [Maybe a] -> [a]
flatten xs = xs >>= f

f :: Maybe a -> [a]
f x = case x of Just j  -> [j]
                Nothing -> []

如果我们在f中提取f构造函数中的值,就可以完全避免g

顺便说一句,f已经存在了,因为maybeToListflatten都在Data.Maybe中被称为catMaybes

票数 4
EN

Stack Overflow用户

发布于 2015-01-06 21:55:54

我们可以很容易地编写一个简单的递归函数,它会遍历一个列表,并拒绝所有可能是单变量的Nothing。下面是我作为递归序列所做的工作:

代码语言:javascript
复制
flatten :: [Maybe a] -> [a]
flatten [] = []
flatten (Nothing : xs) =     flatten xs
flatten (Just x  : xs) = x : flatten xs

然而,把它写成一个折页可能会更清楚:

代码语言:javascript
复制
flatten :: [Maybe a] -> [a]
flatten = foldr go []
    where go  Nothing xs =     xs
          go (Just x) xs = x : xs

或者,我们可以使用一个非常优雅的解决方案,这要感谢@user2407038,我建议在GHCi中使用它来解决单个函数的任务:

代码语言:javascript
复制
flatten :: [Maybe a] -> [a]
flatten = (=<<) (maybe [] (:[])

更快,折起来的兄弟:

代码语言:javascript
复制
flatten :: [Maybe a] -> [a]
flatten = foldr (maybe id (:))

你的解决方案已经走到一半了。我的建议是重写函数f以使用模式匹配(就像我的临时go函数),并将其封装在where语句中,以便将相关函数保存在一个地方。您必须记住scala和Haskell中函数语法的不同。

你最大的问题是你不知道我提到的不同之处。您的g函数可以使用模式匹配和多个模式:

代码语言:javascript
复制
g :: Maybe a -> [a]
g (Just x) = [x]
g  Nothing = []

这样就可以了:您的g函数现在是您所称的“完全”,尽管更准确地说,它具有详尽的模式。

您可以找到关于函数语法这里的更多信息。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27773779

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档