如何在Haskell中实现非参考透明数据结构?

时间:2016-01-26 03:31:49

标签: haskell

我想实现一个数据结构,当我注册它时会给我一个“签名”,因此我可以:

  1. 查询签名是否存在
  2. 合并两个此类DS,同时保持正确的行为
  3. 删除指定的签名
  4. 可能有点模糊,但很容易用Java实现,如下所示:

    class Sig {}
    
    class DesiredDS<A> {
        HashMap<Sig, A> map = new HashMap<>();
    
        public Sig insertWithNewSig(A a) {
            Sig s = new Sig();
            map.put(s, a);
            return s;
        }
        // ...
        // merge will be only to merge to map and delete will be only to delete the key
    }
    

    但我抓住了我的脑袋,无法弄清楚如何在Haskell中使用参考透明度的属性。

    有什么好主意吗?可能与此类似的答案是:如何在Haskell中生成可以比较相等的数据结构,而我不需要打扰决定它的值?

3 个答案:

答案 0 :(得分:4)

最简单的可能是使用

之类的东西
public class MyWebAppInitializer extends AbstractDispatcherServletInitializer {

    @Override
    protected WebApplicationContext createRootApplicationContext() {
        return null;
    }

    @Override
    protected WebApplicationContext createServletApplicationContext() {
        XmlWebApplicationContext cxt = new XmlWebApplicationContext();
        cxt.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml");
        return cxt;
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }

}

你有哪些操作:

  1. 查询签名是否存在

    type Signature a = IORef (Maybe a)
    
  2. 合并两个此类DS,同时保持正确的行为

    (...&#34;正确的行为&#34;?)

  3. 删除指定的签名

    live :: Signature a -> IO Bool
    live ref = isJust <$> readIORef ref
    
  4. 创建新签名

    delete :: Signature a -> IO ()
    delete ref = writeIORef ref Nothing
    
  5. 比较平等

    insertNewSignature :: a -> IO (Signature a)
    insertNewSignature a = newIORef (Just a)
    
  6. 而且,虽然你没有要求它,但大概你实际上不仅要检查签名是否存在,而且还要从签名中恢复值,你有这个操作< / p>

    (==) :: Signature a -> Signature a -> Bool
    

答案 1 :(得分:0)

你有很多选择!如果您希望为随机签名制作唯一性,我建议使用randomness monad来处理您的随机种子,并使用StateT来管理您的HashMap。像这样的东西,粗略地说:

type Sig = -- Something big enough that's an instance of `Random`
newtype DS a = DS (HashMap Sig a)
insert :: (MonadRandom m, MonadState (DS a) m) => a -> m Sig
insert a = do
  ds <- get
  ds' <- HM.insert <$> getRandom <*> pure a
  put ds'

答案 2 :(得分:-3)

使用不安全的I / O是否在作弊?

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

module Lib where

import           Data.Map (Map)
import qualified Data.Map as Map
import           Data.Monoid
import           Data.Unique (Unique)
import qualified Data.Unique as Unique
import           System.IO.Unsafe

newtype Registrar a =
  Registrar (Map Unique a)
  deriving (Eq, Monoid)

insert :: a -> Registrar a -> (Unique, Registrar a)
insert value (Registrar amap) =
  (u, Registrar (Map.insert u value amap))
  where
    u = unsafePerformIO Unique.newUnique

merge :: Registrar a -> Registrar a -> Registrar a
merge = (<>)

delete :: Unique -> Registrar a -> Registrar a
delete signature (Registrar amap) =
  Registrar (Map.delete signature amap)