dingo1337
dingo1337

Reputation: 31

Convert list to nested tuple Haskell

Short and sweet, my issue is that I am parsing a list of numbers ([Integer]), and I want to transform that list into nested tuples, so for example the list [1,2,3,4] would be (1,(2,(3,4))) this seems to me to be doable with a fold operation. I think the problem I am having is that the type is not determined before hand, making the tuple nest potentially infinite.

EDIT BASED ON COMMENTS

Thanks for the good replies, the root problem is for an assignment, so that is why details of the greater issue is sparse, but in an effort to not leave you wondering I can expand a bit, although I am not looking for answers to the expansion. My problem boils down to an issue with a right recursive and right associative part of a context free grammar, where I have something like

A -> n A

so I could get an expression like so 'n n n n A' which parses to 'n(n(n(n A)))' (A does have other terminals). I can parse it to '[n,n,n,n] A', which is why I wanted the conversion (I know there is a better way, I am just struggling to find it).

Upvotes: 3

Views: 299

Answers (1)

leftaroundabout
leftaroundabout

Reputation: 120711

As Thomas M. DuBuisson commented, this is just not really doable in a good way, since the list length is only known at runtime, but tuples of different depth have different types, and types must be known at compile time.

(Technically speaking, Haskell is actually able to act as a full dynamically typed language, by using the Data.Dynamic type, but this really impractical to use.)

There is however another way to have a sensible-ish list-to-tuples conversion: if you do know at compile time what would be the correct depth, and a list of mismatching length should simply be an invalid input. In this case, you can use something like

{-# 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

Upvotes: 5

Related Questions