IT練習ノート

IT関連で調べたこと(実際は嵌ったこと)を書いています。

hetero-mapの使い方

hackage.haskell.org

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

検索しても本当にこのパッケージの情報がなくて、途方に暮れていたところ、HMapexampleがヒントになりました。

Data.HMap

ポイントとしては、

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