我有以下堆排序代码。
heapsort :: (Ord a) => [a] -> [a]
heapsort xs = Heap.toList (Heap.fromList $ xs :: Heap.MinHeap a)
这不会编译并出现以下错误-
mergeLists.hs:32:28: error:
• Couldn't match type ‘a1’ with ‘a’
‘a1’ is a rigid type variable bound by
an expression type signature:
forall a1. Heap.MinHeap a1
at mergeLists.hs:32:50-63
‘a’ is a rigid type variable bound by
the type signature for:
heapsort :: forall a. Ord a => [a] -> [a]
at mergeLists.hs:31:1-33
Expected type: Heap.MinHeap a1
Actual type: Heap.Heap Heap.MinPolicy a
• In the first argument of ‘Heap.toList’, namely
‘(Heap.fromList $ xs :: Heap.MinHeap a)’
In the expression:
Heap.toList (Heap.fromList $ xs :: Heap.MinHeap a)
In an equation for ‘heapsort’:
heapsort xs = Heap.toList (Heap.fromList $ xs :: Heap.MinHeap a)
• Relevant bindings include
xs :: [a] (bound at mergeLists.hs:32:10)
heapsort :: [a] -> [a] (bound at mergeLists.hs:32:1)
|
32 | heapsort xs = Heap.toList (Heap.fromList $ xs :: Heap.MinHeap a)
| ^^^^^^^^^^^^^^^^^^
我认为这是因为函数主体中的a
与函数签名中的a
不同。例如,如果我启用部分类型签名并执行
heapsort :: (Ord a) => [a] -> [a]
heapsort xs = Heap.toList (Heap.fromList $ xs :: Heap.MinHeap _)
代码在编译时显示以下警告(但没有错误)。
λ> :load mergeLists
[1 of 1] Compiling Main ( mergeLists.hs, interpreted )
mergeLists.hs:32:63: warning: [-Wpartial-type-signatures]
• Found type wildcard ‘_’ standing for ‘a’
Where: ‘a’ is a rigid type variable bound by
the type signature for:
heapsort :: forall a. Ord a => [a] -> [a]
at mergeLists.hs:31:1-33
• In an expression type signature: Heap.MinHeap _
In the first argument of ‘Heap.toList’, namely
‘(Heap.fromList $ xs :: Heap.MinHeap _)’
In the expression:
Heap.toList (Heap.fromList $ xs :: Heap.MinHeap _)
• Relevant bindings include
xs :: [a] (bound at mergeLists.hs:32:10)
heapsort :: [a] -> [a] (bound at mergeLists.hs:32:1)
|
32 | heapsort xs = Heap.toList (Heap.fromList $ xs :: Heap.MinHeap _)
| ^
Ok, one module loaded.
那么,如何使用部分类型签名功能来实现此目的?通常,如何在函数定义中使用来自函数签名的类型参数?
答案 0 :(得分:2)
如注释中所示,您可以使用ScopedTypeVariables
扩展名来执行此操作。这使函数主体中使用的类型变量可以引用函数签名中使用的相同变量,但是您必须使用forall
关键字“选择加入”:
{-# LANGUAGE ScopedTypeVariables #-}
import qualified Data.Heap as Heap
heapsort :: forall a . (Ord a) => [a] -> [a]
heapsort xs = Heap.toList (Heap.fromList xs :: Heap.MinHeap a)
在这种特定情况下,您可以通过将Heap.fromList
或Heap.toList
专用于MinHeap
来进行扩展。例如:
heapsort' :: (Ord a) => [a] -> [a]
heapsort' = Heap.toList . minHeapFromList
where minHeapFromList :: (Ord a) => [a] -> Heap.MinHeap a
minHeapFromList = Heap.fromList
在这里,a
和heapsort'
的签名中的minHeapFromList
类型变量是不相关的,但是,当然,它们在heapsort'
的正文中是统一的。