我能够使用GHC9:中的LinearTypes
扩展,成功地从线性基本包中的Data.HashMap.Mutable.Linear
生成HashMap
{-# LANGUAGE LinearTypes #-}
module Main where
import Data.HashMap.Mutable.Linear
import Data.Unrestricted.Linear
main :: IO ()
main = do
let m :: (HashMap Int String %1 -> Ur b) %1 -> Ur b
m = empty 10
let m' = m (h -> toList (insert 1 "s" (insert 2 "w" h)))
let um = unur m'
print um
这看起来很不符合逻辑,因为整个HashMap
必须一次性创建,创建后,我会得到一个[(Int, String)]
。我想继续使用HashMap
来添加、更新、删除项目等。在非线性Haskell中,使用unordered-containers
,它看起来像:
module Main where
import Data.HashMap.Strict
main :: IO ()
main = do
let m :: HashMap Int String
m = empty
let m1 = insert 1 "s" m
-- anywhere else in the code...
let m2 = insert 2 "w" m1
print $ m2
我完全根据文档中的类型编写了前者。empty
似乎与非线性HashMaps
的empty
函数相匹配,但它具有类型
empty :: forall k v b. Keyed k => Int -> (HashMap k v %1 -> Ur b) %1 -> Ur b
上面写着
使用给定容量的空
HashMap
运行计算。
我的理解是,我给它一个Int
作为容量,然后是一个";计算";其将CCD_ 13转换为CCD_。我能找到的唯一满足该类型的函数是toList :: HashMap k v %1 -> Ur [(k, v)]
。其他函数,如insert(insert :: Keyed k => k -> v -> HashMap k v %1 -> HashMap k v
(,都返回一个新的HashMap
(这实际上是我所期望的,但empty
要求我返回Ur b
(。
理想情况下,empty
将返回HashMap
而不是Ur b
,但返回Ur (HashMap ...)
对我来说也很好。有一个签名为a -> Ur a
的函数,它是Ur
构造函数,但如果我用它替换toList
,我得到:
• Couldn't match type ‘'Many’ with ‘'One’
arising from multiplicity of ‘h’
• In the first argument of ‘m’, namely
‘( h -> Ur (insert 1 "s" (insert 2 "w" h)))’
In the expression: m ( h -> Ur (insert 1 "s" (insert 2 "w" h)))
In an equation for ‘m'’:
m' = m ( h -> Ur (insert 1 "s" (insert 2 "w" h)))
|
24 | let m' = m (h -> Ur (insert 1 "s" (insert 2 "w" h)))
| ^
我认为这个想法是将您感兴趣的哈希图计算转移到empty
的延续中,例如,您的第二个示例如下所示:
{-# LANGUAGE LinearTypes #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NoImplicitPrelude #-}
module Main where
import Data.HashMap.Mutable.Linear
import Prelude.Linear hiding (insert)
main :: IO ()
main = print (unur $ empty 10 $ m ->
insert (1 :: Int) "s" m & case
-- anywhere else in the code...
m -> insert 2 "w" m & case
m -> toList m)
这并不好看,但这是我做IO的意思:
{-# LANGUAGE LinearTypes #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE UnboxedTuples #-}
module Main where
import Prelude ((*>))
import Data.HashMap.Mutable.Linear
import Prelude.Linear hiding (insert)
print' :: (Show k, Show v) => HashMap k v %1 -> Ur (IO ())
print' x = toList x & (Ur x1) -> Ur (print x1)
main :: IO ()
main = unur $ empty 10 $ m ->
insert (1 :: Int) "s" m & case
m -> dup m & case
(m1, m) -> print' m1 & case
(Ur io1) -> insert 2 "w" m & case
m -> print' m & case
(Ur io2) -> Ur (io1 *> io2)
可以说,这相当于在这个功能之外进行IO,所以我不知道这有多有用
我想一个更好的解决方案是有一个empty
函数,它明确地允许一种形式的IO