Reputation: 11
Hi I am currently trying to concatenate two lists in Haskell similar to this:
l1 = [[aa,adb,adc], [aa,dd,gg]] l2 = [[cc,abd,hh], [hh, cc, vvvv]] result: l3 = [[aa,adb,adc], [aa,dd,gg], [cc,abd,hh], [hh, cc, vvvv]]
here is my Haskell code:
Length-Ordered Lists over "character type" a (aka "strings over a") Invariant: In LOL n xs, n == length xs Note that automatically-derived Ord instance correctly orders LOLs
data LOL a = LOL Int [a] deriving (Eq,Ord)
instance Show a => Show (LOL a) where
show (LOL n xs) = show xs
-- Empty list (epsilon)
eps :: LOL a
eps = LOL 0 []
establish invariant
lol :: [a] -> LOL a
lol xs = LOL (length xs) xs
Normalized lists of LOLS Lang a implies xs is ordered with no duplicates
type Lang a = [LOL a]
establish invariant
lang :: Ord a => [[a]] -> Lang a
lang xs = norm $ map lol xs
Here is where I am having a problem down below. I can't seem to connect the constructor Lang properly to establish a concatenation.
cat :: Ord a => Lang a -> Lang a -> Lang a
cat (ws) (zs) = [ws:zs | ws++zs, ws <-Lang, zs <-Lang]
Any help will be greatly appreciated!
Upvotes: 1
Views: 362
Reputation: 55069
cat :: Ord a => Lang a -> Lang a -> Lang a
cat (ws) (zs) = [ws:zs | ws++zs, ws <-Lang, zs <-Lang]
This has several syntactic and type errors.
[… | ws ++ zs, …]
tries to use ws ++ zs
as a filter for the list comprehension, but ws ++ zs
is of type Lang a
, not Bool
[… | …, ws <- Lang, zs <- Lang]
shadows the parameters ws
and zs
with new local variables bound inside the comprehension; in addition, Lang
is a type constructor, not a list, so you can’t iterate over it
ws : zs
assumes ws
is an a
and zs
is a [a]
, since the (:)
operator prepends an element to a list, but you’re trying to work with LOL a
values
The Ord
constraint is unnecessary, since you don’t use any comparison functions in the definition of cat
If you’re trying to concatenate every list (of type LOL a
) from one Lang
with every list from the other Lang
, you need to do something like the following:
cat :: Lang a -> Lang a -> Lang a
cat ws zs = [catLol w z | w <- ws, z <- zs]
catLol :: LOL a -> LOL a -> LOL a
catLol (LOL m xs) (LOL n ys) = LOL (m + n) (xs ++ ys)
That is:
w :: LOL a
is bound to each element of ws
Within that loop, z :: LOL a
is bound to each element of zs
The two LOL a
values are concatenated using catLol
catLol
pattern matches on both its arguments to extract the length and list fields
catLol
returns a combined LOL
with a length equal to the sum of the lengths of its operands, and items resulting from concatenating their list fields
This can of course be written without the catLol
helper function:
cat :: Lang a -> Lang a -> Lang a
cat ws zs = [LOL (m + n) (xs ++ ys) | LOL m xs <- ws, LOL n ys <- zs]
But if you’re trying to just concatenate the two Lang a
values, cat
is equal to (++)
, since they’re lists already:
-- Identical to: cat :: [LOL a] -> [LOL a] -> [LOL a]
cat :: Lang a -> Lang a -> Lang a
cat ws zs = ws ++ zs
If you want to normalise the result, then the Ord
constraint makes sense to add back in, and you can just call your norm
function, assuming it has type (Ord a) => Lang a -> Lang a
:
cat :: (Ord a) => Lang a -> Lang a -> Lang a
cat ws zs = norm (ws ++ zs)
Upvotes: 1