haskell - 实现相同功能的不同类型的映射列表?

标签 haskell interface dictionary types

我想对列表(映射)中的每个元素应用一个函数,但这些元素可能具有不同的类型,但都像接口(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 不允许异构列表。因此,您无法创建可输出列表,因为您的 Out1Out2 是两种不同的类型,即使它们都属于同一类型类。

但是有一种解决方法可以使用 ExistentialQuantification 模拟异构列表。 请参阅 heterogeneous lists 的示例在 Haskell wikibook 中。

如何使用

  1. {-# LANGUAGE ExistentialQuantification #-} 放在模块顶部

  2. 定义一个盒子类型,将异构元素隐藏在里面:

      data ShowBox = forall s. Show s => SB s
      heteroList :: [ShowBox]
      heteroList = [SB (), SB 5, SB True]
    
  3. 为框类型本身定义必要的类实例:

      instance Show ShowBox where
        show (SB s) = show s
    
  4. 使用框列表。

一个例子

您的示例可以重写为:

{-# 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/

相关文章:

haskell - FromJSON 实例的单例、类型族和存在类型

haskell - 如何存储和引用递归函数的中间值

haskell - 没有因使用 ‘mymerge’ 而产生 (Ord a0) 的实例

java - 使用 arrayList 中的两个键进行搜索

python - 为什么按顺序将键插入 python dict 比无序插入更快

c - haskell中的递归数据类型

memory - Go 中的接口(interface)是如何表示的?

c# - 如何在单独的库中声明相同的接口(interface)

c# - 如何使用 C# 反序列化 JSON?

java - 如何在 Java 中声明一个 Class<?> 对象,它是一个枚举和一个接口(interface)