我想对列表(映射)中的每个元素应用一个函数,但这些元素可能具有不同的类型,但都像接口(interface)一样实现相同的函数(此处为“putOut”)。但是,我无法创建此“接口(interface)”类型的列表(此处为“可输出”)。
如何映射实现相同功能的不同类型的列表?
import Control.Monad
main :: IO ()
main = do
mapM_ putOut lst
where
lst :: [Outputable] -- ERROR: Class "Outputable" used as a type
lst = [(Out1 1),(Out2 1 2)]
class Outputable a where
putOut :: a -> IO ()
-- user defined:
data Out1 = Out1 Int deriving (Show)
data Out2 = Out2 Int Int deriving (Show)
instance Outputable Out1 where
putOut out1 = putStrLn $ show out1
instance Outputable Out2 where
putOut out2 = putStrLn $ show out2
最佳答案
Haskell 不允许异构列表。因此,您无法创建可输出列表,因为您的 Out1
和 Out2
是两种不同的类型,即使它们都属于同一类型类。
但是有一种解决方法可以使用 ExistentialQuantification
模拟异构列表。
请参阅 heterogeneous lists 的示例在 Haskell wikibook 中。
如何使用
将
{-# LANGUAGE ExistentialQuantification #-}
放在模块顶部定义一个盒子类型,将异构元素隐藏在里面:
data ShowBox = forall s. Show s => SB s heteroList :: [ShowBox] heteroList = [SB (), SB 5, SB True]
为框类型本身定义必要的类实例:
instance Show ShowBox where show (SB s) = show s
使用框列表。
一个例子
您的示例可以重写为:
{-# LANGUAGE ExistentialQuantification #-}
main :: IO ()
main = do
mapM_ print lst
putStrLn "end"
where
lst :: [Printable]
lst = [P (Out1 1),P (Out2 1 2)]
-- box type (2)
data Printable = forall a . Show a => P a
-- necessary Show instance for the box type (3)
instance Show Printable where show (P x) = show x
-- user defined:
data Out1 = Out1 Int deriving (Show)
data Out2 = Out2 Int Int deriving (Show)
关于haskell - 实现相同功能的不同类型的映射列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3061351/