【问题标题】:List of multiple types in HaskellHaskell中多种类型的列表
【发布时间】:2012-10-03 15:44:45
【问题描述】:

假设我有一组记录,如

data A = A { a:: String } deriving (Show)
data B = B { b:: String } deriving (Show)

然后是一些类型类

class Foo a where
    foo :: a -> IO ()

instance Foo A where
    foo c = ...

我也想做类似的事情

bar = do
    push (A {a="x"})
    push (B {b="y"})

然后将这些东西放在一个列表中,以便稍后在某个地方运行,这样我就可以

map foo l

我是否应该编写模板 haskell 来生成包装器类型并派生实例以便列表可以是包装器类型?有没有更聪明的方法来解决这个问题?老实说,我对 haskell 类型系统感到非常困惑,并且知道必须有更好的方法来做到这一点。

【问题讨论】:

    标签: generics haskell types functional-programming polymorphism


    【解决方案1】:

    一个使用 Existential 的示例,但我真的会放弃使用它,并会建议 hammar 所说的内容。

    {-# LANGUAGE ExistentialQuantification #-}
    data A = A String deriving Show
    data B = B String deriving Show
    
    class Foo a where
        foo :: a -> IO ()
    
    instance Foo A where
        foo c = putStrLn $ "FOOA " ++ show c
    
    instance Foo B where
        foo c = putStrLn $ "FOOB " ++ show c
    
    data Wrap = forall a . Foo a => Wrap a
    
    instance Foo Wrap where
        foo (Wrap c) = foo c
    
    bar :: [Wrap]
    bar = [Wrap $ A "x", Wrap $ B "y"]
    
    main = mapM_ foo bar
    

    【讨论】:

      【解决方案2】:

      存在量化有很多方法可以做到这一点,但它通常是矫枉过正的。一种更符合 Haskell 的方法是简单地预先应用 foo 并保留结果操作的 [IO ()] 列表,然后您可以稍后通过 sequence 运行它们。

      【讨论】:

      • 因此您可以将thingsToDo :: [IO()] 定义为thingsToDo = [foo A, foo B] 甚至stuffToDo :: IO ()stuffToDo = foo A >> foo B
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-05-19
      • 2018-02-04
      • 1970-01-01
      • 2020-02-16
      • 2021-06-16
      • 2017-08-07
      • 1970-01-01
      相关资源
      最近更新 更多