gpt4 book ai didi

haskell - 创建 Haskell 'init' 函数的安全版本

转载 作者:行者123 更新时间:2023-12-02 02:56:42 25 4
gpt4 key购买 nike

我正在研究“真实世界 Haskell”,任务是制作 head, tail, last, 的安全版本。和 init.我在前三个上成功了,但是 Maybe typeclass 在 init 上杀了我.
这是我的代码:

-- safeInit
safeInit :: [a] -> Maybe [a]
safeInit [] = Nothing
safeInit (x:xs) = if null xs
then Just [x]
else x : (safeInit xs)
这是加载到 GHCI 时产生的错误(该函数从原始文件的第 23 行开始:
[1 of 1] Compiling Main             ( ch04.exercises.hs, interpreted )

> ch04.exercises.hs:27:26: error:
> • Couldn't match expected type ‘Maybe [a]’ with actual type ‘[a]’
> • In the expression: x : (safeInit xs)
> In the expression: if null xs then Just [x] else x : (safeInit xs)
> In an equation for ‘safeInit’:
> safeInit (x : xs) = if null xs then Just [x] else x : (safeInit xs)
> • Relevant bindings include
> xs :: [a] (bound at ch04.exercises.hs:25:13)
> x :: a (bound at ch04.exercises.hs:25:11)
> safeInit :: [a] -> Maybe [a] (bound at ch04.exercises.hs:24:1) | 27 | else x : (safeInit xs) |
> ^^^^^^^^^^^^^^^^^
>
> ch04.exercises.hs:27:31: error:
> • Couldn't match expected type ‘[a]’ with actual type ‘Maybe [a]’
> • In the second argument of ‘(:)’, namely ‘(safeInit xs)’
> In the expression: x : (safeInit xs)
> In the expression: if null xs then Just [x] else x : (safeInit xs)
> • Relevant bindings include
> xs :: [a] (bound at ch04.exercises.hs:25:13)
> x :: a (bound at ch04.exercises.hs:25:11)
> safeInit :: [a] -> Maybe [a] (bound at ch04.exercises.hs:24:1) | 27 | else x : (safeInit xs) |
> ^^^^^^^^^^^ Failed, no modules loaded.
我以任何方式标记或不标记 xxs在最后两行 Just ,我得到了不同但非常相关的打字错误。我错过了在列表中使用 Maybe 类型的哪些微妙之处?

最佳答案

这不起作用的主要原因是因为你的表达 x : safeInit xs不会类型检查。确实,safeInit xsMaybe [a] ,但是 (:)有类型 (:) :: a -> [a] -> [a] ,所以类型不匹配。
还有一个语义错误。如 null xsTrue ,那么你应该返回 Just []而不是 Just [x] , 从此x是列表中的最后一个元素。
您可以使用 fmap :: Functor f => (a -> b) -> f a -> f b (所以对于 f ~ Maybefmapfmap :: (a -> b) -> Maybe a -> Maybe b ),改变包裹在 Just 中的值:

safeInit :: [a] -> Maybe [a]
safeInit [] = Nothing
safeInit [_] = Just []
safeInit (x:xs) = fmap (x:) (safeInit xs)
但这将导致 Just 中值的大量包装和展开.这也意味着对于无限列表,它将陷入无限循环。我们可以简单地检查列表是否至少包含一个元素,然后执行初始化逻辑作为我们包装在 Just 中的函数的结果。 :
safeInit :: [a] -> Maybe [a]
safeInit [] = Nothing
safeInit (x:xs) = Just (go xs x)
where go [] _ = []
go (x2:xs) x = x : go xs x2

关于haskell - 创建 Haskell 'init' 函数的安全版本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62597105/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com