【问题标题】:Convert list to nested tuple Haskell将列表转换为嵌套元组 Haskell
【发布时间】:2020-02-28 17:13:29
【问题描述】:

简短而甜蜜,我的问题是我正在解析一个数字列表([Integer]),我想将该列表转换为嵌套元组,例如列表 [1,2,3,4] 将be (1,(2,(3,4))) 在我看来,这似乎可以通过折叠操作来实现。我认为我遇到的问题是类型不是事先确定的,这使得元组嵌套可能是无限的。

根据评论进行编辑

感谢您的良好回复,根本问题是分配,所以这就是为什么更大问题的细节很少,但为了不让你想知道我可以扩展一点,虽然我不是在寻找扩展的答案。我的问题归结为上下文无关语法的右递归和右关联部分的问题,我有类似

A -> n A

所以我可以得到一个像'n n n n A'这样的表达式,它解析为'n(n(n(n A)))'(A确实有其他终端)。我可以将其解析为 '[n,n,n,n] A',这就是我想要转换的原因(我知道有更好的方法,我只是在努力寻找)。

【问题讨论】:

  • 您不能这样做,因为类型取决于数据(完全取决于依赖类型)。
  • 感谢您的回答,这有点像我所了解的,但希望我监督了一些事情。
  • 您可以定义自己的自定义类型data T = Empty | Nonempty (Integer, T) 来表示元组的任意嵌套,但这样做只是为标准列表类型赋予了另一个名称,因此没有任何好处。为什么你认为你的数据需要元组?
  • 另一种可能的编码:data NTup t = Here t | There (NTup (Integer,t))。然后,您可以将NTup () 用于任何大小的嵌套元组。当你递归到Here 时,t 将是一个适当大小的嵌套元组(尝试showing 看看)。这被称为非常规类型,在这种情况下我真的看不出这样做的意义,但这是一个很好的技术。

标签: list haskell types tuples


【解决方案1】:

正如 Thomas M. DuBuisson 评论的那样,这并不是真正可行的好方法,因为列表长度仅在运行时知道,但不同深度的元组具有不同的类型,并且类型必须在编译时知道。

(从技术上讲,Haskell 实际上可以通过使用Data.Dynamic 类型来充当完全动态类型的语言,但这确实不切实际。)

但是,还有另一种方法可以进行合理的列表到元组的转换:如果您确实在编译时知道正确的深度是多少,那么长度不匹配的列表应该简单是一个无效的输入。在这种情况下,您可以使用类似

{-# LANGUAGE FunctionalDependencies, FlexibleInstances #-}

class NestedTup e t where
  toNestedTup :: [e] -> Maybe t

instance NestedTup e e where
  toNestedTup [e] = Just e
  toNestedTup _ = Nothing
instance NestedTup h t => NestedTup h (h,t) where
  toNestedTup (h:t) = (h,)<$>toNestedTup t
  toNestedTup [] = Nothing
*Main> toNestedTup [1,2,3,4 :: Int] :: Maybe (Int,(Int,(Int,Int)))
Just (1,(2,(3,4)))
*Main> toNestedTup [1,2,3,4,5 :: Int] :: Maybe (Int,(Int,(Int,Int)))
Nothing

【讨论】:

  • 您是如何在实例定义中添加类型约束的,它是如何工作的? ghci 还抱怨打开 TupleSections
  • @Yogendra 你可以这样做。 instance &lt;constraints&gt; =&gt; ClassName params。它的工作原理是首先 选择没有约束的实例,提交该选择,然后尝试解决约束。 (把它想象成一个“如果那么”,虽然很诱人,但会诱使你认为你可以做你不能做的事情)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-11
  • 1970-01-01
  • 2011-03-05
  • 1970-01-01
  • 2019-12-28
相关资源
最近更新 更多