0

I have created a data group:

data Cars = vw | audi | ford
data Engine = TDI | TSI 

I want to use these in a function/list comprehension. To show combinations I have this:

[(x,y) | x <- Cars , y <- Engine]

But I'mm a little bit lost on how to use the data within a function.

I get this error:

Not in scope: data constructor `Cars'
1
  • Please also note, that names for type constructors and type names them selves both have to start with a capital letter. Commented Mar 22, 2011 at 18:47

3 Answers 3

11

Cars and Engine are types, nothing more, especially not lists of constructors. To get a collection of all constructors of a type, make it an instance of Enum and perhaps Bounded (you can derive both, Bounded is not necessary but nice as it allows not hardcoding the start value). See e.g. this question (in particular, this answer). Copying and adjusting that code (also, I fixed the casing of the ctors and renamed Cars as it was plural and not very specific):

data CarManufacturer = VW | Audi | Ford deriving (Bounded, Enum)
data Engine = TDI | TSI deriving (Bounded, Enum)

allValues :: (Bounded a, Enum a) => [a]
allValues = [minBound..]

allEngines = allValues :: [Engine]
allCars = allValues :: [CarManufacturer]

carsWithEngines = [(car, engine) | car <- allCars, engine <- allEngines]
Sign up to request clarification or add additional context in comments.

3 Comments

I like this better than my approach; but it would be nice if you added the deriving clauses to your code.
+1 I like the idea of a generic allValues function, that never occurred to me. I know plenty of cases where this could save some code in my programs.
@Ferich: Even better, it's not a function but a friggin' polymorphic constant. Try beating that, average type system.
3

Is that what you want?

$cat t.hs
data Cars = Vw | Audi | Ford 
        deriving (Enum, Show)
data Engine = TDI | TSI  
        deriving (Enum, Show)


main = print [(x,y) | x <- [Vw .. Ford] , y <- [TDI .. TSI]]


$ghc t.hs

$./a.out 
[(Vw,TDI),(Vw,TSI),(Audi,TDI),(Audi,TSI),(Ford,TDI),(Ford,TSI)]

1 Comment

You gonna splain what's going on here?
1

Unfortunately you can't access the constructors of a datatype this way. First, all data constructors need to be capitalized, so change to this:

data Cars = VW | Audi | Ford deriving Show
data Engine = TDI | TSI      deriving Show

-- create explicit lists of the constructors
carTypes :: [Cars]
carTypes = [VW, Audi, Ford]

engineTypes :: [Engine]
engineTypes = [TDI, TSI]

now you can use these lists in a list comprehension

> let ll = [(x,y) | x <- carTypes, y <- engineTypes]
> show ll
> [(VW,TDI),(VW,TSI), (Audi,TDI),(Audi,TSI),(Ford,TDI),(Ford,TSI)]
> :type ll
> ll :: [(Cars,Engine)]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.