Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 列表上的可能和递归_Haskell - Fatal编程技术网

Haskell 列表上的可能和递归

Haskell 列表上的可能和递归,haskell,Haskell,我尝试使用Maybe实现反转功能。我不知道如何使用递归在模式匹配中返回。例如,ghci>myReverse[1,2,3]需要返回Just[3,2,1]。这是我的密码: myReverse :: [a] -> Maybe [a] myReverse [] = Nothing myReverse [x] = Just [x] myReverse (x:xs) = myReverse xs ++ [x] -- here's my problem. 我原以为myReverse(x:xs)=只要$

我尝试使用
Maybe
实现
反转
功能。我不知道如何使用递归在模式匹配中返回
。例如,
ghci>myReverse[1,2,3]
需要返回
Just[3,2,1]
。这是我的密码:

myReverse :: [a] -> Maybe [a]
myReverse [] = Nothing
myReverse [x] = Just [x]
myReverse (x:xs) = myReverse xs ++ [x] -- here's my problem.
我原以为
myReverse(x:xs)=只要$myReverse-xs++[x]
就行了,但是不行,我不知道怎么做。我想知道的是怎么做以及为什么


谢谢你的帮助

myReverse
返回一个
可能[a]
,它不能直接附加到某个内容,因为它不是列表。如果
myReverse xs
的值为
Nothing
,或者
Just
。你需要对结果进行模式匹配

myReverse (x:xs) = 
    case myReverse xs of
         Just list -> ...
         Nothing   -> ...
当然,您需要根据您希望
myReverse
做什么来决定在这些情况下需要做什么


还请记住,并非每个函数都需要递归,因此如果需要,可以从
myReverse
调用常规的
reverse

我想到了与luqui类似的方法,除了在末尾应用Maybe:

myReverse :: [a] -> Maybe [a]
myReverse ys
  | null (myReverse' ys) = Nothing
  | otherwise            = Just (myReverse' ys)
 where
   myReverse' []     = []
   myReverse' (x:xs) = myReverse' xs ++ [x]
或者,如果你愿意

myReverse ys | null (reverse ys) = Nothing
             | otherwise         = Just (reverse ys)

由于
[a]
是一个幺半群

instance Monoid [a] where
        mempty  = []
        mappend = (++)
那么,
可能[a]
也是一个幺半群

instance Monoid a => Monoid (Maybe a) where
    mempty = Nothing
    Nothing `mappend` m = m
    m `mappend` Nothing = m
    Just m1 `mappend` Just m2 = Just (m1 `mappend` m2)
注意实例声明中的类型约束,它将
a
强制为幺半群,否则
可能a
不会

然后,我们可以使用mappend,
()
,在将列表头转换为单例的条件下链接递归调用

import Data.Monoid ((<>))

myReverse :: [a] -> Maybe [a]
myReverse []     = Nothing
myReverse (x:xs) = myReverse xs <> Just [x]
这可以改写为

>>> foldl' (\x y -> y:x) [] [1..5]
[5,4,3,2,1]
为了适应Maybe类型,我们进行以下转换

  • 种子
    []
    变成
    (只是[])
  • 匿名函数现在必须在内部应用,我们使用fmap来实现它
这就导致我们,

>>> foldl' (\x y -> fmap (y:) x) (Just []) [1..5]
Just [5,4,3,2,1]
最后,

mreverse xs | null xs = Nothing 
            | foldl' (\x y -> fmap (y:) x) (Just []) xs

这将始终返回
Nothing
或抛出错误,因为
否则=True
。你是说更像是
let reversed=myReverse'ys in in如果null reversed,那么就没有其他东西可以反转了吗
?哦,我把模式误读为一个表达式。我从未想过调用通配符大小写
否则
,因为它会成为
序曲的阴影。否则
。很酷的解释…那么
myReverse[]
的“Nothing”呢?我们可以使用pattern guard来管理这个情况,
mreverse xs | null xs=Nothing |否则=foldl'(\x y->fmap(y:)x)(Just[]))xs
我已经尝试了一段时间,但我不知道如何实现编码部分中建议的递归(我假设它应该只取代vildric代码的最后一行)。你能给我/我们一个提示吗?我能想到的应用编码部分的唯一方法是使用mappend,正如zurgl所提到的,但是case语法似乎是多余的,因为你可以编写
myReverse(x:xs)=mappend(myReverse-xs)(只是[x])
。使用大小写语法:
myReverse[]=Nothing;case myxs的反方向为Nothing->Just[x];否则->mappend(myReverse-xs)(仅[x])
。有没有办法在没有mappend的情况下实现编码部分?您甚至没有使用大小写绑定的值!在
Just list->
案例中,
list
是一个类型为
[a]
的值,您可以根据需要对其执行操作。。。例如
Just(list++[x])
。在任何情况下,这个答案都是“低电平”,如果它出现在我的代码中,我会认为它是一种气味;我通常更喜欢按照您的建议使用
mappend
。我只是想让它对初学者来说是好的和具体的。它不起作用,或者至少我不能让它起作用。我玩弄了各种各样的表达式,包括
(list++[x])
。你能展示一个没有mappend的工作示例吗?@groovy也许你可以问另一个关于它的问题?只是出于好奇,你为什么不实现与原来的
reverse
函数相同的行为?为什么空列表的反面不能是空列表?是的,可以,但目标是更多地了解Haskell(面对这种问题迫使你尝试许多解决方案并寻找答案,因此你学习新事物)。
>>> foldl' (\x y -> fmap (y:) x) (Just []) [1..5]
Just [5,4,3,2,1]
mreverse xs | null xs = Nothing 
            | foldl' (\x y -> fmap (y:) x) (Just []) xs