0
votes

here are the concerning data definition

data Decl = Decl Name Type

data FunDecl = FunDecl Type Name [Decl] [Decl] Cmd

newtype Program = Program [FunDecl]

what i wanna do is to filter the [FunDecl] with the name of "main"

filterByname :: Program -> Program
filterByname (Program p) =
  let p_main = filter (\FunDecl Type name [Decl] [Decl] cmd -> Name == "main") in Program $ p_main p

but i get the error message of "Not in scope: data constructor ‘Type’" how can i solve it ?

1

1 Answers

2
votes

You appear to be confusing types/type constructors with variable names. [Decl] is a type, and Decl is both a type constructor and a type (data Decl = Decl ...), so neither are valid variable names - you want to assign an identifier to the value you'll be passed (which is of type [Decl]) so you need to use an identifier like decl1 for it (may be worth looking over this tutorial).

Words beginning with an uppercase letter can only be types and type constructors - only words beginning with lowercase (and that aren't restricted) can be identifiers (see this Q/A or the grammar specification).


So you need to change your lambda:

\(FunDecl declType name decl1 decl2 cmd) -> name == "main"

The FunDecl stays, as it's a type constructor that we're pattern matching against, where the identifiers given to the matched parts are called name, decl1 etc.

Name is also changed to name in the lambda body so that we refer to the argument, not to the type constructor Name.


Given that you're only using the name argument, you can also define your lambda as:

\(FunDecl _ name _ _ _) -> name == "main"

Where _ is a "special" identifier which means "an argument that we don't want to give a name". This is usually better practice.