haskell - 有没有办法将一种类型的构造函数也用作类型?

标签 haskell

例如:

data Foo = Bar Int | Baz String

我想使用如下功能:

qux :: [Foo] -> [Baz]
qux fs = filter f fs
    where
        f (Baz _) = True
        f _ = False

通常,我需要:

data Bar = Bar Int
data Baz = Baz String

data Foo = FBar Bar | FBaz Baz

qux = ...

但我对这个解决方案并不满意,因为它需要大量冗余代码。

有没有一种优雅的方法来解决这个问题?

最佳答案

一种可能性是使用 GADTs 。其要点是,这使我们能够拥有所谓的 "phantom" type argument到数据类型定义。我们可以用它做的一件事是限制使用此数据类型的函数(例如)的类型,以便它仅适用于可由特定构造函数创建的值。

以下是我如何编写您以这种风格提供的示例(注意:您需要启用 GADTs 扩展):

{-# LANGUAGE GADTs #-}
data BarType -- Note: These could be called Bar and Baz, but I named them this for clarity
data BazType

data Foo a where
    Bar :: Int -> Foo BarType
    Baz :: Int -> Foo BazType

有了这个,你可以编写这样的函数:

onlyAcceptsBars :: Foo BarType -> Int
onlyAcceptsBars (Bar bar) = -- ...
-- There would be a compile-time error if you had a case like this:
--    onlyAcceptsBars (Baz baz) = ...

onlyAcceptsBazs :: Foo BazType -> Int
onlyAcceptsBazs (Baz baz) = -- ...

acceptsAnyFoo :: Foo a -> Int
acceptsAnyFoo (Bar bar) = -- ...
acceptsAnyFoo (Baz baz) = -- ...

关于haskell - 有没有办法将一种类型的构造函数也用作类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20530801/

相关文章:

haskell - 为什么我的并行遍历 Haskell 程序会泄漏内存?

haskell - `pure x = (\_ -> x)` 是什么意思?

haskell - 在 Haskell 中生成相同元素的无限列表

haskell - Haskell 中的 $ 运算符给出数据构造函数错误

haskell - 从子查询中选择并连接 Esqueleto 中的子查询

haskell - 类型族内的多态函数

haskell - Haskell 中的 GC 在软实时应用程序中暂停

haskell - 如何在haskell中执行 "break"IO操作

haskell - 为什么函数 (+) 匹配类型 (a -> b -> b)?

haskell - 如何在 Haskell 中添加/减去绝对值和相对值的运算符