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 !
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.