
Hi! I am new to Haskell, but I have background in various programming languages (including Lisp) I have very basic question, if there is a way to match algebraic types constructors besides use of pattern matching. I wrote today code like this: data Flag = Verbose | Input String | Output String | Filter String deriving Show instance Eq Flag where Verbose == Verbose = True Input _ == Input _ = True Output _ == Output _ = True Filter _ == Filter _ = True _ == _ = False findFlag :: Flag -> [Flag] -> Flag findFlag f [] = f findFlag y (x:xs) = if x == y then x else findFlag y xs If there is a cleaner way to implement findFlag and Eq Flag? Vadim -- "La perfection est atteinte non quand il ne reste rien a ajouter, mais quand il ne reste rien a enlever." (Antoine de Saint-Exupery)

On Fri, 5 Mar 2004, Vadim Zaliva wrote:
Hi!
I am new to Haskell, but I have background in various programming languages (including Lisp)
I have very basic question, if there is a way to match algebraic types constructors besides use of pattern matching. I wrote today code like this:
data Flag = Verbose | Input String | Output String | Filter String deriving Show
instance Eq Flag where Verbose == Verbose = True Input _ == Input _ = True Output _ == Output _ = True Filter _ == Filter _ = True _ == _ = False
findFlag :: Flag -> [Flag] -> Flag findFlag f [] = f findFlag y (x:xs) = if x == y then x else findFlag y xs
If there is a cleaner way to implement findFlag and Eq Flag?
Vadim
It looks like you are doing some sort of option processing. There have been some suggestions recently for better approaches on the haskell list. See the thread "High-level technique for program options handling" from January. The basic idea there is to define a record type holding your options in the most useful form for your program, and turn your arguments into functions that transfrom such a record, rather than values you need to analyze. The example in Tomasz Zeilonka's post has exactly the option structure of your code. At the lower level of remimplementing your functions I can suggest a few things. It's probably overkill, but the Data typeclass provides an operation that takes a value and returns the constructor used. Add "Data" to the list of typeclasses you want to derive, and you can write your equality function as (GHC only) x == y = toConstr x == toConstr y For your findFlag function, the library function "find" is nearly what you want, except it returns a value in Maybe rather than taking a default: findFlag :: Flag -> [Flag] -> Maybe Flag findFlag f fs = find (==f) fs You could use the "maybe" function (Maybe a -> b -> (a->b) -> b) to supply the default. Brandon
-- "La perfection est atteinte non quand il ne reste rien a ajouter, mais quand il ne reste rien a enlever." (Antoine de Saint-Exupery)
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On Mar 5, 2004, at 12:41, Brandon Michael Moore wrote:
At the lower level of remimplementing your functions I can suggest a few things.
Brandon, Thanks for great suggestions! Following them, here is how I redone the code: ... import Data.Maybe import Data.Either import Data.Typeable ... data Flag = Verbose | Input String | Output String | Filter String deriving Show Data instance Eq Flag where x == y = toConstr x == toConstr y findFlag :: Flag -> [Flag] -> Flag findFlag f fs = fromMaybe f (find (==f) fs) The only problem is my GHC does not seems to find 'Data' class and I am getting following errors: Type constructor or class not in scope: `Data' Variable not in scope: `toConstr' Variable not in scope: `toConstr' Also I have style question: What is the best way to define equality test in this example: 1. Via instantiating EQ class 2. via standalone function (I can define sameConstr Flag -> Flag -> Bool) 3. inline lambda expression passed to find I am leaning towards #2 or #3. Vadim -- "La perfection est atteinte non quand il ne reste rien a ajouter, mais quand il ne reste rien a enlever." (Antoine de Saint-Exupery)

On Mar 5, 2004, at 15:48, Vadim Zaliva wrote: OK, I figured it out. For sake of other novices like me here is what you need to do to make it work. 0. Need to import Data.Generics 1. Compile with '-fglasgow-exts' flag 2. When deriving from Data you also need to derive from Typeable. It slightly bothers me that this solution seems to be using non-standard GHC extensions. Vadim
On Mar 5, 2004, at 12:41, Brandon Michael Moore wrote:
At the lower level of remimplementing your functions I can suggest a few things.
Brandon,
Thanks for great suggestions! Following them, here is how I redone the code:
...
import Data.Maybe import Data.Either import Data.Typeable
...
data Flag = Verbose | Input String | Output String | Filter String deriving Show Data
instance Eq Flag where x == y = toConstr x == toConstr y
findFlag :: Flag -> [Flag] -> Flag findFlag f fs = fromMaybe f (find (==f) fs)
The only problem is my GHC does not seems to find 'Data' class and I am getting following errors:
Type constructor or class not in scope: `Data' Variable not in scope: `toConstr' Variable not in scope: `toConstr'
Also I have style question: What is the best way to define equality test in this example:
1. Via instantiating EQ class 2. via standalone function (I can define sameConstr Flag -> Flag -> Bool) 3. inline lambda expression passed to find
I am leaning towards #2 or #3.
Vadim
-- "La perfection est atteinte non quand il ne reste rien a ajouter, mais quand il ne reste rien a enlever." (Antoine de Saint-Exupery)
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-- "La perfection est atteinte non quand il ne reste rien a ajouter, mais quand il ne reste rien a enlever." (Antoine de Saint-Exupery)

On Mar 8, 2004, at 11:17, Sven Panne wrote:
Hmmm, using generics seems like massive overkill for option handling. Could you describe what you are exactly trying to achieve?
I am doing command line options parsing. I've defined Flag type with constructor for each possible option: data Flag = Verbose | Input String | Output String | Filter String deriving (Show, Typeable, Data) getOpt returns me a list of such objects. Now I need to look things up there by constructor. For example: .... doSomething fltflag where (Filter fltflag) = findFlag (Filter "none") opts To achieve this I've defined: instance Eq Flag where x == y = toConstr x == toConstr y findFlag :: Flag -> [Flag] -> Flag findFlag f fs = fromMaybe f (find (==f) fs) Sincerely, Vadim -- "La perfection est atteinte non quand il ne reste rien a ajouter, mais quand il ne reste rien a enlever." (Antoine de Saint-Exupery)

On Mon, 8 Mar 2004, Vadim Zaliva wrote:
I am doing command line options parsing. I've defined Flag type with constructor for each possible option:
data Flag = Verbose | Input String | Output String | Filter String deriving (Show, Typeable, Data)
getOpt returns me a list of such objects. Now I need to look things up there by constructor. For example:
.... doSomething fltflag where (Filter fltflag) = findFlag (Filter "none") opts
Try this instead: doSomething $ option "none" [fltflag | Filter fltflag <- opts] ... option :: a -> [a] -> a option def [] = def option def [x] = x option def _ = error "Only one of each option allowed" -- Ben

On Mar 8, 2004, at 12:55, Ben Rudiak-Gould wrote: This would work, but I will have to write [] part for each option. Generics approach is overkill but looks much neater when used. But thanks for suggestion anyway, it is always good to learn yet another way of doing things. Sincerely, Vadim
Try this instead: doSomething $ option "none" [fltflag | Filter fltflag <- opts]
option :: a -> [a] -> a option def [] = def option def [x] = x option def _ = error "Only one of each option allowed"
-- "La perfection est atteinte non quand il ne reste rien a ajouter, mais quand il ne reste rien a enlever." (Antoine de Saint-Exupery)

How about this approach ? I think this is a conventional and clear way, though Flag Verbose has a verbose String. ----- import Data.List import Data.Maybe data Flag = Flag FlagType String deriving Show getFlagType (Flag ft _) = ft data FlagType = Verbose | Input | Output | Filter deriving (Show, Eq) findFlag f@(Flag ft _) xs = fromMaybe f (find ((ft ==).getFlagType) xs) -- instance Eq Flag where -- Flag ft1 _ == Flag ft2 _ = ft1 == ft2 ---- -- Koji Nakahara
participants (5)
-
Ben Rudiak-Gould
-
Brandon Michael Moore
-
Koji Nakahara
-
Sven Panne
-
Vadim Zaliva