【问题标题】:Generalize the method signature of a function in haskell.泛化haskell中函数的方法签名。
【发布时间】:2013-10-14 16:11:15
【问题描述】:

我是 Haskell 的新手,并试图了解它是如何工作的。 我想在 Haskell 中定义一个可以获取元组列表的函数,这些元组可以是对、3 元组、4 元组、5 元组等

functionY [(a,b)] 

那么我不能用像[(1,2,3),(2,3,4)]这样的三元组元素来调用它

functionY  [(1,2,3),(2,3,4)] // will complain 

我将如何解决这个问题? 谢谢

【问题讨论】:

  • 我不确定这是否可能——因为元组是高度特定的类型,而且它们也没有自己的类型类。在 GHC 中,Data.Tuple 本身只涉及配对。如果我错了,其他人可能会纠正我。
  • 好的,一些搜索给了我:Yampatuple 包。看看他们的来源,看看他们是如何处理这个问题的。他们确实为 n 元组定义了多个函数。 tuple 包使用fundeps来解决这个问题。
  • 忽略编译器错误,你会怎么写functionY
  • @Steve314 不需要 Haskell 模板;请参阅HList,它仅将 TH 用于非必要的 MakeLabels 模块。
  • @Steve314 概念进展是这样的:(a, b, c, d)(a, (b, (c, (d, ())))) 大致相同;写 cons = (,)nil = () 我们可以在这种类型中拥有一个值 cons a (cons b (cons c (cons d nil)));然后,天哪,这看起来有点像异构列表!

标签: haskell


【解决方案1】:

这是一种方法,如果您不介意编写一些样板代码,则该方法适用。从概念上讲,关于 n 元组的所有重要之处在于它是一个具有 n 个插槽的数据结构,您可以访问它。 n >= m 的每个 n 元组都应该有一个名为 get-m 的方法,该方法获取第 m 个插槽中的任何数据。我们可以通过使用函数依赖将其抽象为类型类

{-# LANGUAGE FunctionalDependencies, FlexibleInstances #-}

class HasFirst a b | a -> b where
    get1 :: a -> b

class HasSecond a b | a -> b where
    get2 :: a -> b

这些类型类描述具有“第一”和“第二”槽的数据。我们可以为 2-tuples 和 3-tuples 编写实例如下

instance HasFirst (a,b) a where
    get1 (a,_) = a

instance HasSecond (a,b) b where
    get2 (_,b) = b

instance HasFirst (a,b,c) a where
    get1 (a,_,_) = a

instance HasSecond (a,b,c) b where
    get2 (_,b,_) = b

现在您可以编写一个通用的函数,该函数适用于所有具有“第二个”插槽的数据结构,例如

getSeconds :: HasSecond a b => [a] -> [b]
getSeconds = map get2

并按如下方式使用

>>> getSeconds [(1,2), (4,5)]
[2,5]
>>> getSeconds [(1,2,3), (4,5,6)]
[2,5]

【讨论】:

    猜你喜欢
    • 2016-09-30
    • 1970-01-01
    • 2018-07-25
    • 1970-01-01
    • 2011-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多