【问题标题】:Haskell: How can I define a type class for sets?Haskell:如何为集合定义类型类?
【发布时间】:2012-07-16 16:36:27
【问题描述】:

这里的新手,苦苦挣扎。

我正在尝试为集合定义一个类型类。对于这种情况,它只需要“存在”的定义。 'exists' 将在一个集合项上接受一个集合和函数,然后返回 一个布尔值。我如何在 Haskell 中定义它?

下面的方向是否正确?所以有类型类定义和一个 set with list 的实现,'exists' 现在返回 true ..

-- Set.hs --

class Set a b where

  exists :: a -> (b -> Bool) -> Bool


-- ListSet.hs --

instance Set ListSet a where 

  exists a f = True

--

(结果:类 `Set' 的参数太多)

【问题讨论】:

    标签: haskell set typeclass


    【解决方案1】:

    你可以这样做,有足够的扩展。至少,您将需要多参数类型类。但是,使用起来会很烦人:您需要在各处指定显式类型签名。解决它的一种方法是引入函数依赖(使用另一个扩展):

    class Set a b | a -> b where
        exists :: a -> (b -> Bool) -> Bool
    

    这就是说,如果你知道集合的类型,你也知道元素的类型。但是,有一种更简单的方法,无需任何扩展即可工作:

    class Set f where
        exists :: f a -> (a -> Bool) -> Bool
    

    在这里,类型类涵盖了更高种类的类型,这是一个巧妙的技巧,如果您以前从未见过,很难自己想出它!

    【讨论】:

    • 当然,后者要求元素类型是集合类型的最后一个类型参数——这并不总是可行的,比如你想为a -> Bool 创建一个实例。另一方面,关联类型族可以很好地解决这个问题。
    • 谢谢!我得到了第二种方法!我必须承认我不太明白那里发生了什么,但希望它向我展示自己......
    【解决方案2】:

    Daniel Wagner 已经对您正在尝试做的事情给出了完美的答案。我只想补充一点关于您的错误 - Too many parameters for class 'Set'。这意味着您没有启用相应的 GHC 扩展 - MultiParamTypeClasses。您可以通过在源文件顶部指定特殊类型的注释来做到这一点:

    {-# LANGUAGE MultiParamTypeClasses #-}
    --
    -- Your source code here
    --
    

    那么你应该可以编译你的代码了。

    丹尼尔的回答中提到的另一个 Haskell 功能也需要启用某些扩展,即FunctionalDependencies(这是类型类声明中奇怪的.. | a -> b .. 东西)。您可以使用逗号同时启用多个扩展,如下所示:

    {-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}
    

    Carl 的评论提到了另一个扩展,TypeFamilies,它也可以为您尝试做的事情提供方法(集合类型的泛型类或其他类型的集合)。你可以在这里阅读:http://www.haskell.org/haskellwiki/Type_families

    【讨论】:

    • 我也设法用函数依赖方法做到了。但是,我还必须包含“FlexibleInstances”扩展名。
    猜你喜欢
    • 1970-01-01
    • 2017-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多