关于foldl1(Haskell)的错误

时间:2014-01-09 23:29:07

标签: haskell fold

我有一个数据类型:

BinHeap a = [BinTree a]

BinTree a = Node a i (BinHeap a)

我想要一个函数通过Bintree a并给我最小的a。

extractMin :: BinHeap a -> a
extractMin ps
 = foldl1 (\(Node x y z) (Node x' y' z') -> Node (smaller x x') y z) ps
 where
  smaller x y = if x <= y then x else y

它崩溃了。同时我不知道为什么。因为fold1中的函数输出BinTree,所以它不应该崩溃。

感谢您的时间

2 个答案:

答案 0 :(得分:2)

您的数据类型显示BinTree,这似乎意味着“二叉树”,但它没有被定义为二叉树。它甚至不是有效的语法,所以我不太确定你的数据类型是什么(BinHeaptype还是data?为什么有两种数据类型,而不是一种数据类型和2个构造函数?)

如果您在foldl1列表中使用BinTree a,那么您的输出将是BinTree a,而不是a。正确的类型签名是extractMin :: Ord a => BinHeap a -> BinTree a

函数smaller已存在,称为min

最惯用的方式可能是使用Data.Foldable,它会自动为minimum个实例提供Foldable

import Data.Foldable
import Prelude hiding (minimum)
import Data.Monoid

data Tree a = Tree a [Tree a] | Leaf

instance Foldable Tree where
    -- foldMap :: Monoid m => (a -> m) -> Tree a -> m
    foldMap _ Leaf = mempty
    foldMap f (Tree a xs) = f a `mappend` mconcat (map (foldMap f) xs)

minTree :: Ord a => Tree a -> a
minTree = minimum

答案 1 :(得分:0)

我不知道你的代码有什么问题,但我可以看到两种可能性:

  • 类型参数(a)没有实现Ord的约束。因此,您无法在较小的函数中对它们进行比较。

  • 传递给foldl1的lambda表达式应该在括号中。否则,编译器会理解它运行到行尾。