Scala 在Haskell中实现列表扁平化

Scala 在Haskell中实现列表扁平化,scala,haskell,Scala,Haskell,Scala提供了一种从List[Option[a]到List[a]的plant方法 scala> val list = List(Some(10), None) list: List[Option[Int]] = List(Some(10), None) scala> list.flatten res11: List[Int] = List(10) 我试图在Haskell中实现它: flatten :: [Maybe a] -> [a] flatten xs = map g

Scala提供了一种从
List[Option[a]
List[a]
plant
方法

scala> val list = List(Some(10), None)
list: List[Option[Int]] = List(Some(10), None)

scala> list.flatten
res11: List[Int] = List(10)
我试图在Haskell中实现它:

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
是一个部分函数,即非全部函数


有没有一种方法可以编写这样的
展平
函数?

您的
展平
catMaybes
相同,定义如下:

catMaybes :: [Maybe a] -> [a]
catMaybes ls = [x | Just x <- ls]
catMaybes::[maybea a]->[a]

catMaybes ls=[x | Just x对您的代码稍加修改即可:

flatten :: [Maybe a] -> [a]
flatten xs = xs >>= f

f :: Maybe a -> [a]
f x = case x of Just j  -> [j]
                Nothing -> []
如果我们只在
f
中的
构造函数中提取
中的值,我们将完全避免
g


顺便说一句,
f
已经存在,并且在
数据中调用了
flatten
。也许

可以很容易地编写一个简单的递归函数,它遍历一个列表,并拒绝来自Maybe monad的所有
Nothing
。下面是我如何作为递归序列来做的:

flatten :: [Maybe a] -> [a]
flatten [] = []
flatten (Nothing : xs) =     flatten xs
flatten (Just x  : xs) = x : flatten xs
但是,将其写成折页可能更为清晰:

flatten :: [Maybe a] -> [a]
flatten = foldr go []
    where go  Nothing xs =     xs
          go (Just x) xs = x : xs
或者,由于@user2407038,我们可以使用一个非常优雅的解决方案,我建议在GHCi中使用它来解决各个函数的工作:

flatten :: [Maybe a] -> [a]
flatten = (=<<) (maybe [] (:[])
你的解决方案已经走到了一半。我的建议是,如果重写你的函数
f
,使用模式匹配(比如我的临时
go
函数),并将其包含在
where
语句中,将相关函数保留在一个地方。你必须记住scala和Haskell中函数语法的差异

您遇到的最大问题是不知道我提到的差异。您的
g
函数可以对多个模式使用模式匹配:

g :: Maybe a -> [a]
g (Just x) = [x]
g  Nothing = []
你的
g
函数现在就是你所谓的“complete”,尽管更准确地说,它有详尽的模式


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

concatMap(可能是[](:[]))
Complete是足够准确的,尽管艺术术语是“total”,而不是“partial”。
g :: Maybe a -> [a]
g (Just x) = [x]
g  Nothing = []