Haskell 使用maybe进行列表渲染错误的模式匹配
分解模式时,我应该如何使用Haskell 使用maybe进行列表渲染错误的模式匹配,haskell,pattern-matching,maybe,Haskell,Pattern Matching,Maybe,分解模式时,我应该如何使用Just构造函数? 例如:如果我的模式是:(x1,x2,x3,.xn)我将不得不用它的将模式的每个元素括起来 我的问题:我正在尝试“安全地”实现Init函数。我是否必须在第二行中对尾部和头部使用 safeInit::[a]->Maybe [a] safeInit (x:xs)=x: safeInit (Just xs) #Just x : safeInit Just xs ? safeInit [x,y]=Just [x] safeInit _ =Nothing
Just
构造函数?
例如:
如果我的模式是:
(x1,x2,x3,.xn)
我将不得不用它的将模式的每个元素括起来
我的问题:我正在尝试“安全地”实现Init函数。
我是否必须在第二行中对尾部和头部使用
safeInit::[a]->Maybe [a]
safeInit (x:xs)=x: safeInit (Just xs) #Just x : safeInit Just xs ?
safeInit [x,y]=Just [x]
safeInit _ =Nothing
这里有两个问题:
- 你打电话时输入一个
可能是[a]
;及
- 第一个模式包含一个(严格的)超集,然后是第二个模式,因此第二个模式永远不会触发
对于第一个问题,罪魁祸首是:
safeInit (x:xs) = x: safeInit (Just xs)
在这里,safeInit
,需要一个列表(键入[a]
),但是您将列表包装在Just
构造函数中,因此您向它传递了一个Maybe[a]
值,而safeInit
无法处理此问题。因此,我们可以将其改写为:
safeInit (x:xs) = x : safeInit xs
然而,这并不能解决问题,因为现在我们将上的“cons”(:
)称为a
,并且可能[a]
,同样,函数无法处理此问题。我们首先必须检查递归调用是否生成一个safeInit
,然后在x
前面加上一个Just
,我们可以使用fmap
:
safeInit (x:xs) = fmap (x:) (safeInit xs)
对于第二个问题,我们可以重新安排条款:
safeInit :: [a] -> Maybe a
safeInit [x, _] = Just [x]
safeInit (x:xs) = fmap (x:) (safeInit xs)
safeInit [] = Nothing
尽管如此,这种方法仍然存在一些问题:它相当低效,因为我们只为所有元素(最后一个除外)展开并包装元素,因为它没有得到优化。此外,如果我们处理一个无限列表,我们将陷入一个无限循环。我们可以通过使用一个内部函数来改进它,该函数计算init
,因为我们确信init
是有效的。例如:
safeInit :: [a] -> Maybe a
safeInit (x:xs) = Just (go x xs)
where go _ [] = []
go x (x2:xs) = x : go x2 xs
safeInit [] = Nothing
这取决于你想要什么语义学。在init
的情况下,一旦找到任何元素,就知道结果实际上是Just
,即Just initxs
。然后,您希望将当前的x
添加到包含的列表中,而不更改的任何内容,只更改。最简单的方法是使用Maybe
的Functor
实例:
safeInit (x:xs) = (x:) <$> safeInit xs
扩展Elmex80的建议
safeInit :: [a] -> Maybe [a]
safeInit [] = Nothing
safeInit xs = Just (init xs)
使用safeInit(x:xs)=Just(init(x:xs))
。我不想使用开箱即用的方法。不过还是要谢谢你。但是你不是这样更改初始列表吗?@bercoviciarian:你不能更改Haskell中的任何内容,所有变量都是不可变的。你认为我在以什么方式改变初始列表?不,你没有改变我以为你是在x后面加x…你只是在用“x2”进一步分解。我很抱歉。
safeInit (x:xs) = case safeInit xs of
Just init_xs -> Just $ x : init_xs
Nothing -> Just []
safeInit [] = Nothing
safeInit :: [a] -> Maybe [a]
safeInit [] = Nothing
safeInit xs = Just (init xs)