如何创建通用地图

时间:2018-11-15 12:24:16

标签: haskell

我可以像这样从Int[Bool]创建一个简单的地图

import Data.Map (Map)
import qualified Data.Map as Map

simpleMap :: Map Int [Bool]
simpleMap = 
  Map.insert 1 [True, False] .
  Map.insert 1 [False, True] $ Map.empty

编译器告诉我此映射的类型为

simpleMap :: Map Int [Bool]

这一切都很好。

现在,如果我写类似

的内容,我想创建一个从Just a[a]的通用地图。
genericMap :: Map (Maybe a) [a]

genericMap = 
  Map.insert (Just True) [True, False] .
  Map.insert (Just False) [False, True] $ Map.empty

我收到以下编译错误

* Couldn't match type `a' with `Bool'
  `a' is a rigid type variable bound by
    the type signature for:
      genericMap :: forall a. Map (Maybe a) [a]
    at test.hs:23:1-31
  Expected type: Map (Maybe a) [a]
    Actual type: Map (Maybe Bool) [Bool]

但是,这样的编译还是可以的

genericMap2 :: (Ord a, Num a) => Map (Maybe a) [a]

genericMap2 = 
  Map.insert (Just 1) [1, 2] .
  Map.insert (Just 2) [3, 4] $ Map.empty

我在这里做什么错了?


更新

这只是一个学习练习。理想情况下,我想创建一个HigherMap数据类型,看起来像这样(用伪代码):

{
  Just 1 -> [1, 2, 3],
  Just True -> [True, False],
  Just "abc" -> ["def", "ghi"]
}

其中的键和值都来自类型构造函数,并且我捕获到两个类型参数相同的信息。

1 个答案:

答案 0 :(得分:4)

类似Map (Maybe a) [a]的类型意味着使用此变量的人将决定要为a使用哪种类型。这不适用于您的genericMap定义,因为它试图在其中放置Bool值,我可能想在其他类型上使用它。

genericMap2是可以的,因为它使用了多态常数:1 :: (Num a) => a,因此它可以用于任何(数字)类型,而不像True :: Bool具有固定类型。