在Haskell中,如何使用';头部';不创建单独的函数?

在Haskell中,如何使用';头部';不创建单独的函数?,haskell,head,Haskell,Head,我对使用Haskell非常陌生,我不确定“头”是如何工作的。据我所知,它返回列表中的第一个元素。我一直在尝试使用它,但我总是出错。我添加了一个解决方法,创建了一个单独的函数来查找头部,但是这似乎是不必要的 我不明白为什么打电话给findHead: single x = length (snd(x)) == 1 toList board | board == [] = [] | otherwise = filter single board findHead board = h

我对使用Haskell非常陌生,我不确定“头”是如何工作的。据我所知,它返回列表中的第一个元素。我一直在尝试使用它,但我总是出错。我添加了一个解决方法,创建了一个单独的函数来查找头部,但是这似乎是不必要的

我不明白为什么打电话给findHead:

single x = length (snd(x)) == 1

toList board
    | board == [] = []
    | otherwise = filter single board

findHead board = head (toList board)
不等同于在此处调用toList:

single x = length (snd(x)) == 1

toList board
    | board == [] = []
    | otherwise =  head (filter single board)
在我看来,这两个应该是一样的,但只有第一个运行。为什么它们不能被解释为相同的呢?你能给我解释一下吗?在上面的代码中,“board”是指元组列表,每个元组的形式为(x,[a,b,…])

我在一些简单的事情中使用了“头”,例如:

union xs ys 
  | xs == [] = ys
  | ys == [] = xs
  | otherwise = union (tail xs)  (add (head xs) ys)
这似乎和我预期的一样有效。

头部是局部的。特别是,
head[]
不会正常返回(抛出异常)。这在Haskell中可能很难处理,这就是为什么人们经常建议您避免使用部分函数

那我们怎么做呢?我们必须在类型中反映失败

对于
tail

safeTail :: [a] -> Maybe [a]
safeTail []     = Nothing
safeTail (a:as) = Just as

我认为您需要后退一步,了解模式匹配、递归和单链表是如何工作的。正如许多人提到的,您正在编写的代码不会很好地工作

以下是我如何在您的问题中编写各种函数的示例:

single :: (a, [b]) -> Bool    
single (_, [_]) = True
single _ = False

toList :: [(a, [b])] -> [(a, [b])]
toList board = filter single board

findHead :: [(a, [b])] -> Maybe (a, [b])
findHead [] = Nothing
findHead board = head (toList board)

-- This one actually does the same thing as the built-in `++` operator,
-- but for the sake of illustration, I'll implement it.
union :: [a] -> [a] -> [a]
union [] ys = ys
union (x:xs) ys = x : union xs ys

“但只有第一个运行”-这是否意味着第二个挂起,或者它产生不同的输出,或者导致错误?在这两种情况下,您都需要调用
head
,即通过更改
| board=[]=head[]
。然后,我希望你能明白为什么
头部
在这里是个坏主意。在绝大多数情况下,与部分投影(如
头部
尾部
)相比,更喜欢(详尽的!)模式匹配。顺便说一句,你不应该使用
=[]
检查空列表。这无缘无故地施加了一个
Eq
约束,看起来很奇怪。您通常应该在这种上下文中使用模式匹配,而不是保护<例如,code>union[]ys=ys
union(x:xs)ys=union-xs(x:ys)
。如果您确实想要一个“是否为空”,您应该使用
null
。此外,询问列表的长度是否为1可能比将其与
[x]
[\u]
模式匹配的效率低得多。此外,在将来,如果您用英语告诉我们代码应该做什么和实际做什么,并给出一个实际的测试用例,这将非常有帮助。否则,弄清楚如何修复它就像读茶叶一样。
single :: (a, [b]) -> Bool    
single (_, [_]) = True
single _ = False

toList :: [(a, [b])] -> [(a, [b])]
toList board = filter single board

findHead :: [(a, [b])] -> Maybe (a, [b])
findHead [] = Nothing
findHead board = head (toList board)

-- This one actually does the same thing as the built-in `++` operator,
-- but for the sake of illustration, I'll implement it.
union :: [a] -> [a] -> [a]
union [] ys = ys
union (x:xs) ys = x : union xs ys