简体   繁体   中英

Creating a data type list Haskell

I've done a personal list in Haskell like this: (2,(1,1),3) -> List [Num 2, List [Num 1, Num 1], List [Num 3]].

This is how I made it:

data SList a = Num a | List [SList a] deriving Show
emptySList :: SList a
emptySList = (List [])

consElem :: a -> SList a -> SList a
consElem x (List y) = (List ((Num x) : y))

consList :: SList a -> SList a -> SList a
consList a b = (List [a,b])

I manage to form this list (List [Num 2, List [Num 1, Num 1], List [Num 3]]) using consElem and consList like this:

consElem 2 $ consList (consElem 1 $ consElem 1 emptySList) $ consElem 3 emptySList

I wonder how can I transform a SList in a normal list. For example if I have this SList: List [Num 2, List [Num 1, Num 1], List [Num 3]] it should become [2,1,1,3] .

My attempt:

atomToNormal x
    | null x = []
    | otherwise = slistToList (head x) ++ atomToNormal (tail x)
slistToList :: SList a -> [a]
slistToList (List x) = atomToNormal x
slistToList (Num x) = [x]

GHC can actually write this function for you:

{-# LANGUAGE DeriveFoldable #-}
import Data.Foldable as Foldable

data SList a = Num a | List [SList a]
  deriving (Show, Foldable)

slistToList :: SList a -> [a]
slistToList = Foldable.toList

If you want to do it yourself – I don't see quite what atomToNormal is supposed to do, you don't need it. Just deconstruct the tree-branch list head-first right in slistToList :

slistToList :: SList a -> [a]
slistToList (Num x) = _
slistToList (List []) = _
slistToList (List (l:ls)) = _

Now fill in the gaps. GHC (>=7.10) can help you a lot there too: just try compiling as-is with the underscore-gaps, and it will tell you

/tmp/wtmpf-file17703.hs:8:23:
    Found hole ‘_’ with type: [a]
    Where: ‘a’ is a rigid type variable bound by
               the type signature for slistToList :: SList a -> [a]
               at /tmp/wtmpf-file17703.hs:7:16
    Relevant bindings include
      x :: a (bound at /tmp/wtmpf-file17703.hs:8:18)
      slistToList :: SList a -> [a]
        (bound at /tmp/wtmpf-file17703.hs:8:1)
    In the expression: _
    In an equation for ‘slistToList’: slistToList (Num x) = _

So the first gap needs to have type [a] , and the only value you have is x::a . Well, you can wrap that in a singleton list

slistToList (Num x) = [x]

Proceed in the same fashion with the other clauses. As a rule of thumb, if you just somehow include all of the “relevant bindings” (often, there's exactly one way to do this), then your implementation will probably be right.

Of course, this only works when you first write out the type signature... which should always be the first thing you do anyway !


Your type really should be called something tree-ish, not SList !

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM