hetero-mapの使い方
hetero-map
パッケージを使おうと思ったのですが、サンプルが見つけられず、使い方に悩みました。
このようにして、型の整合はとれても、undefined
をつかっているので実行時にエラーになります。
*Main HeteroMap.Map> let k1 = undefined :: Key Char Char *Main HeteroMap.Map> let k2 = undefined :: Key Int Int *Main HeteroMap.Map> let m = insert k2 2 $ insert k1 'a' empty *Main HeteroMap.Map> :t m m :: Map (Int HeteroMap.Map.:* (Char HeteroMap.Map.:* HeteroMap.Map.Z)) *Main HeteroMap.Map> let v = lookup k1 m *Main HeteroMap.Map> v *** Exception: Prelude.undefined CallStack (from HasCallStack): error, called at libraries/base/GHC/Err.hs:79:14 in base:GHC.Err undefined, called at <interactive>:19:10 in interactive:Ghci2 *Main HeteroMap.Map>
Key
の実装は
data Key x a where Key :: Key a a
となっていますが、データコンストラクタは公開されていません。
key
を作る実装も関数cc
を与えるだけになっており、関数を与えるけれど、その関数の第1引数はKey
固定になっています。これはどのように使うのでしょうか?
-- | Allocate a new key, which is only valid within the passed function -- (and will be a type error if it tries to escape). newKey :: (forall x. Key x a -> b) -> b newKey cc = cc Key
検索しても本当にこのパッケージの情報がなくて、途方に暮れていたところ、HMap
のexample
がヒントになりました。
ポイントとしては、
1つの関数の中で閉じて使う。別の関数とMapを共有できない。(<-この理解であってる?)
ということのようです。
import HeteroMap.Map import Prelude hiding (lookup) example :: Key aaa String -> Key bbb Double -> Key ccc Bool -> String example name salary female = format a ++ "\n" ++ format b ++ "\n" where a = insert name "Edsger" $ insert salary 4450.0 $ insert female False empty b = insert name "Ada" $ insert salary 5000.0 $ insert female True empty format x = lookup name x ++ ": salary=" ++ show (lookup salary x) ++ ", female=" ++ show (lookup female x) keyLocal :: String keyLocal = newKey $ newKey $ newKey example main = do print "local" putStr keyLocal