Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/118.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell型包装器_Haskell - Fatal编程技术网

Haskell型包装器

Haskell型包装器,haskell,Haskell,我有一系列函数,如: f1 :: String -> String -> ... -> String -> () f1 a b ... z = g [("a", a), ("b", b), ... ("z", z)] ... fn :: String -> Int -> String -> ... -> String -> () fn a b ... z = g [("a", a), ("b", show b), ... ("z", z)]

我有一系列函数,如:

f1 :: String -> String -> ... -> String -> ()
f1 a b ... z = g [("a", a), ("b", b), ... ("z", z)]
...
fn :: String -> Int -> String -> ... -> String -> ()
fn a b ... z = g [("a", a), ("b", show b), ... ("z", z)]
所以用户可以像
f1“abc”“def”
那样调用它们。我不希望他这样做,因为他可以很容易地错误地交换“abc”和“def”(天知道调试时会浪费多少时间)。我想让他传递像
fk(A“abc”)(B“def”)
据我所知,有两种选择:

  • 海量
    数据
    构造和海量解包功能:

    data Value = A String
               | B String
               | C Int
               | D String
               ...
    
     unpack :: Value -> String
     unpack (A a) = a
     unpack (B b) = b
     unpack (C c) = show c
     unpack (D c) = d
    
    很多代码

  • 通用类型类和新类型:
    编辑:好的,我们可以在这种简单的情况下使用
    generalizednewtypedering

      {-# LANGUAGE GeneralizedNewtypeDeriving #-}
    
      class Value a where
        unpack :: a -> String
      instance Value String where
        unpack = id
      instance Value Int where
        unpack = show
    
      newtype A = A String deriving Value
      newtype B = B String deriving Value
      newtype C = C Int deriving Value
      newtype D = D String deriving Value
    
      ...
    
    看起来好多了,但所有的
    fk
    看起来都像

       fk a b ... z = g [("a", unpack a), ("b", unpack b), ... ("z", unpack z)]
    
    大量的代码和重复

  • 我想要的是一些魔术,可以让我:

  • fk a b。。。z=g[(“a”,a),(“b”,b),…(“z”,z)]
  • g=h。地图(第二次解包)

  • 我认为问题可以归结为:列表只能有相同类型的元素;这意味着要么您必须在
    f
    中将其“合并”为单个类型,要么您不能依赖Haskell的类型检查。例如,以下代码适用于您,但类型检查是运行时的:

    {-# LANGUAGE GADTs #-}
    
    import Control.Arrow (second)
    
    data Item where
        A :: String -> Item
        B :: Int -> Item
    
    unpack (A s) = s
    unpack (B i) = show i
    
    myf a@(A {}) b@(B {}) c@(B {}) = 
        let g = [("a", a), ("b", b), ("c", c)]
        in map (second unpack) g
    myf _ _ _ = error "Bad types"
    
    main = do
        putStrLn $ show $ myf (A "test") (B 13) (B 14)
        putStrLn $ show $ myf (A "test") (B 13) (A "xxx")
    
    当您需要编译时类型检查时,您可以执行以下操作:;但是,您仍然需要将参数重新键入相同的类型,因此在某种意义上,解包与解包之间没有太大区别,只是可能会稍微减少出错的可能性。json包提供了一个很好的技巧——它们重新定义了一些操作符(例如=:)来创建类型,因此您可以:

    {-# LANGUAGE ExistentialQuantification #-}
    import Control.Arrow (second)
    
    class Value a where
        unpack :: a -> String
    newtype A = A String
    newtype B = B Int
    
    instance Value A where
        unpack (A a) = a
    
    instance Value B where
        unpack (B b) = show b
    
    data Item = forall b. Value b => Item b
    a =: b = (a, Item b)
    
    myf :: A -> B -> B -> [(String, String)]
    myf a b c = 
        let g = ["a" =: a, "b" =: b, "c" =: c]
        in map (second (\(Item x) -> unpack x)) g
    
    main = do
        putStrLn $ show $ myf (A "test") (B 13) (B 14)
    
    不过,这与仅仅定义
    a=:b=(a,unpack b)
    没有太大区别