仅在选择构造函数时比较数据类型值

时间:2016-07-02 06:58:01

标签: haskell types comparison

我想比较数据类型的构造函数“tag”。

有一种简单的方法吗?

5

2 个答案:

答案 0 :(得分:4)

您可能希望将构造函数与通配符进行模式匹配。像这样:

...
var initVectorBytes = Encoding.UTF8.GetBytes(initVector);
var saltValueBytes = Encoding.UTF8.GetBytes(saltValue);
var plainTextBytes = Encoding.UTF8.GetBytes(plainText);
string cipherText;
using (var memoryStream = new MemoryStream())
{
  using (var password = new PasswordDeriveBytes(passPhrase, saltValueBytes, hashAlgorithm, passwordIterations))
  {
    var keyBytes = password.GetBytes(keySize/8);
    using (var symmetricKey = new RijndaelManaged {Mode = CipherMode.CBC})
    {
      var encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes);
      var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
      cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
      cryptoStream.FlushFinalBlock();
      var cipherTextBytes = memoryStream.ToArray();
      cipherText = Convert.ToBase64String(cipherTextBytes);
    }
  }
}
return cipherText;
...

答案 1 :(得分:2)

有几种方法可以做到这一点,没有一种方法是完美的。

您可以通过比较数据种类类型代表来执行类似操作:

{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeApplications #-}
import Data.Typeable

data D = A | B Int | C Char

kCheck :: Typeable a => Proxy (a::k) -> D -> Bool
kCheck p d = typeRep p == kTypeRep where
  kTypeRep = case d of
    A    -> typeRep (Proxy @ 'A)
    B {} -> typeRep (Proxy @ 'B)
    C {} -> typeRep (Proxy @ 'C)

(如果你没有ghc 8.0.1删除TypeApplications并将@ 'A替换为:: Proxy 'A)我认为这需要ghc 7.10(或者可能是7.8 {{1} }})。

AutoDeriveTypeable

或者您可以使用kCheck (Proxy @ 'B) (B 3) True kCheck (Proxy @ 'C) A False 并比较TemplateHaskell s:

Name

如果您对比较字符串感到满意,可以使用{-# LANGUAGE TemplateHaskell #-} import Language.Haskell.TH data D = A | B Int | C Char thCheck :: Name -> D -> Bool thCheck n d = n == conName where conName = case d of A -> 'A B {} -> 'B C {} -> 'C > thCheck 'B (B 3) True > thCheck 'A (C 'a') False 中的toConstr自动导出字符串:

Data

有一种最接近你想要的方法但这只有在每个类型构造函数具有不同类型时才有效。 因此{-# LANGUAGE DeriveDataTypeable #-} import Data.Data data D = A | B Int | C Int deriving Data dCheck :: String -> D -> Bool dCheck s d = s == show (toConstr d) data D = A Int | B Int的类型代表都是A ,所以这不会与B一起使用。

Int -> D

按预期工作:

{-# LANGUAGE DeriveDataTypeable #-}

import Data.Typeable

data D = A | B Int | C String
  deriving Typeable

check :: Typeable a => a -> D -> Bool
check p d = typeOf p == conTypeRep
  where
    conTypeRep = case d of
      A    -> typeOf A
      B {} -> typeOf B
      C {} -> typeOf C