【问题标题】:Recursion with tuple types元组类型的递归
【发布时间】:2017-10-08 17:17:03
【问题描述】:

我一直在努力处理一个应该返回嵌套元组的函数。具体来说,函数的输入给我带来了很多问题。简化版如下:

tupfnc :: ?????
tupfnc [a] = (a,()) --
tupfnc (a:as) = (a,tupfnc as)

这个想法是接受一个项目列表(比如[0,1,5,3])并将它们嵌套到一个像这样的元组中:(0,(1,(5,(3,()))))

我最初的想法是这样声明:

tupfnc :: [a] -> (a,b)

但是,(本示例的)第三行抛出此错误:

Solver.hs:56:17: error:
    • Couldn't match expected type ‘(a, b)’
                  with actual type ‘[(a, (a, b0))]’
    • In the expression: [(a, tupfnc as)]
      In an equation for ‘tupfnc’: tupfnc (a : as) = [(a, tupfnc as)]
    • Relevant bindings include
        as :: [a] 
        a :: a 
        tupfnc :: [a] -> (a, b) 

【问题讨论】:

  • 这里有几件事。首先,您的“数组”(这是一个列表)将始终包含 same 类型。您不能拥有[0,1,'a',3],因为'a' 不是Int。接下来,您返回一个列表或一个元组,但它们的类型不同,所以这也是不可能的。最后但并非最不重要的一点是,(a,b)(a,(a,b)) 类型不同,除非 b ~ (a,b) 因此是无限的。您必须使用data InPair a = Stop | InPair a (InPair a) 来创建它,但现在您又回到了一个列表。您是否在寻找类型级别的非同质列表?
  • 我的错,我在写这个问题的时候头脑不清醒。我已将其编辑为更正确。列表的项目都应该属于同一类型。你对 b~(a,b) 的评论更符合我的期待。我不知道如何定义一个返回无限类型的函数(这就是它们的名称吗?)。我还要看看类型级别的非同质列表
  • 即使进行了编辑,您仍会返回 (a, ())[(a, …)]。您返回一个列表或一个元组,但它们是不同的类型。这似乎是一个 XY 问题。你到底想做什么?
  • 混蛋。我的意思是只返回元组——我再次编辑了它。很抱歉把事情搞砸了。这实际上不是 XY 问题,我确实想知道如何通过递归处理元组(即为 tupfunc 找到正确的类型)——我只是可怕地扼杀了我尝试的 SSCCE 实现。
  • 你想要可变长度的元组,不幸的是,haskell 不支持,这就是为什么 fst 函数只适用于对,即使它应该适用于任何大小的元组

标签: haskell recursion tuples


【解决方案1】:

除非您有关于列表长度的类型级信息,否则这是不可能的。想象一个名为Vector 的列表变体,在这种情况下,您可以执行以下操作:

{-# LANGUAGE GADTs, PolyKinds, DataKinds, TypeFamilies, TypeOperators #-}

-- | Peano natural numbers
data Nat = Z | S Nat

-- Just for convenience...
type N0 = Z
type N1 = S N0
type N2 = S N1
type N3 = S N2
type N4 = S N3
type N5 = S N4
type N6 = S N5
type N7 = S N6
type N8 = S N7
type N9 = S N8

-- | Equivalent to a list, but carries information about its length with it
data Vector (n :: Nat) a where
  Nil    :: Vector Z a
  (:-)   :: a -> Vector n a -> Vector (S n) a

infixr 5 :-

现在,我们可以定义一个类型族,将数字转换为相应的嵌套元组:

type family NestedTuple (n :: Nat) (a :: *) where
  NestedTuple Z     a = ()
  NestedTuple (S n) a = (a, NestedTuple n a)

最后我们可以定义一个函数,将Vector n a 转换成它的嵌套元组形式。

toList :: Vector n a -> NestedTuple n a
toList Nil = ()
toList (x :- xs) = (x, toList xs)

您可以在 GHCi 上进行测试:

ghci> :set -XFlexibleContexts
ghci> toList ("foo" :- "bar" :- "baz" :- Nil)
("foo",("bar",("baz",())))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多