san*_*ten 5 haskell list maybe
我对haskell很新,不知道如何使用Maybe [a].通常我正在编写OOP(VB.NET)并且在我的空闲时间我想学习haskell(不要问为什么;)).
那么,我想做什么?我想读取两个带有数字ID的文件,并找出两个文件中匹配的ID.阅读文件并不是一件大事,它的工作非常简单.现在,我得到两个列表Maybe[Ids](简单的例子,只是认为ID是Int).所以我需要的功能看起来像这样
playWithMaybe :: (Maybe [a]) -> (Maybe [Int]) -> [Int]
Run Code Online (Sandbox Code Playgroud)
现在我想像以前一样访问列表成员
playWithMaybe (x:xs) (y:ys) = undefined
Run Code Online (Sandbox Code Playgroud)
但不幸的是,这是不允许的,GHC对两个名单都说
Couldn't match expected type ‘Maybe [Int]’ with actual type ‘[t0]’
Run Code Online (Sandbox Code Playgroud)
所以我玩了一下但没有办法访问列表成员.有人可以帮我吗?一点点解释将是一件好事!
为了从不同的方向解决你的问题,我认为你不想要一个处理两个问题的函数Maybe [a].忍受我:
从根本上说,您要执行的操作在两个列表上运行,为您提供一个新列表,例如,
yourFunction :: [a] -> [a] -> [a]
yourFunction a b = ...
Run Code Online (Sandbox Code Playgroud)
那很好,你可以而且应该这样写yourFunction.您拥有的数据会Maybe [a]捕获一些额外的辅助信息:创建输入列表的操作可能已失败.下一步是yourFunction与辅助信息链接在一起.这正是do符号的目的,将纯操作(如yourFunction)与上下文混合(事实上,您的某个输入列表的创建可能已失败):
playWithMaybe :: Maybe [a] -> Maybe [a] -> Maybe [a]
playWithMaybe maybeA maybeB =
do a <- maybeA -- if A is something, get it; otherwise, pass through Nothing
b <- maybeB -- if B is something, get it; otherwise, pass through Nothing
Just (yourFunction a b) -- both inputs succeeded! do the operation, and return the result
Run Code Online (Sandbox Code Playgroud)
但事实证明,你可能想要使用其他类型的上下文(一个简单的上下文,而不Maybe只是捕获"发生了一些不好的事情",我们可以Either用来捕获"发生了一些不好的事情,这里是对什么的描述"回过头来看playWithMaybe," Maybe-ness"只出现在一个地方,Just最后一行.事实证明,Haskell提供了一个通用函数pure来包装一个纯值,就像我们得到的那样yourFunction,在最小的上下文中:
playWithMaybe' :: Maybe [a] -> Maybe [a] -> Maybe [a]
playWithMaybe' maybeA maybeB =
do a <- maybeA
b <- maybeB
pure (yourFunction a b)
Run Code Online (Sandbox Code Playgroud)
但是后来Haskell也有一个泛型类型来抽象出一个上下文的概念,即Monad.这让我们的功能更加通用:
playWithMonad :: Monad m => m [a] -> m [a] -> m [a]
playWithMonad mA mB =
do a <- mA
b <- mB
pure (yourFunction a b)
Run Code Online (Sandbox Code Playgroud)
现在我们有一些非常通用的东西,事实证明它是如此通用,它已经在标准库中了!(这是非常微妙的,所以不要担心,如果它还没有意义.)
import Control.Applicative
play :: Monad m => m [a] -> m [a] -> m [a]
play mA mB = liftA2 yourFunction mA mB
Run Code Online (Sandbox Code Playgroud)
甚至
import Control.Applicative
play' :: Monad m => m [a] -> m [a] -> m [a]
play' = liftA2 yourFunction
Run Code Online (Sandbox Code Playgroud)
为什么我突然从Monad切换到Applicative?Applicative类似于Monad,但更通用,所以如果你选择的话,通常最好使用Applicative(类似于我选择使用pure而不是return之前).有关更完整的解释,我强烈建议您了解一下Haskell(http://learnyouahaskell.com/chapters),特别是第11章和第12章.注意 - 请务必先阅读第11章!Monad只有掌握了Functor和Applicative之后才有意义.
一般来说:
yourFunction Nothing Nothing = ...
yourFunction (Just xs) Nothing =
case xs of
[] -> ...
x':xs' -> ...
-- or separately:
yourFunction (Just []) Nothing = ...
yourFunction (Just (x:xs)) Nothing = ...
Run Code Online (Sandbox Code Playgroud)
等等.哪些案例需要单独处理取决于具体的功能.您更有可能将处理函数的函数Maybe与工作函数结合起来[].
如果你想"只返回一个没有元素的列表" Nothing,那么你可以写
maybeToList1 :: Maybe [a] -> [a]
maybeToList1 Nothing = []
maybeToList1 (Just xs) = xs
Run Code Online (Sandbox Code Playgroud)
编写相同函数的更好方法是maybeToList1 = maybe [] id(docs formaybe)或者maybeToList1 = fromMaybe [],但是因为你刚刚开始,你可能想稍后回到这个.