Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
333 views
in Technique[技术] by (71.8m points)

haskell - Test if a value matches a constructor

Say I have a data type like so:

data NumCol = Empty |
              Single Int |
              Pair Int Int |
              Lots [Int]

Now I wish to filter out the elements matching a given constructor from a [NumCol]. I can write it for, say, Pair:

get_pairs :: [NumCol] -> [NumCol]
get_pairs = filter is_pair
    where is_pair (Pair _ _) = True
          is_pair _ = False

This works, but it's not generic. I have to write a separate function for is_single, is_lots, etc.

I wish instead I could write:

get_pairs = filter (== Pair)

But this only works for type constructors that take no arguments (i.e. Empty).

So the question is, how can I write a function that takes a value and a constructor, and returns whether the value matches the constructor?

question from:https://stackoverflow.com/questions/25587501/test-if-a-value-matches-a-constructor

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

At least get_pairs itself can be defined relatively simply by using a list comprehension to filter instead:

get_pairs xs = [x | x@Pair {} <- xs]

For a more general solution of matching constructors, you can use prisms from the lens package:

{-# LANGUAGE TemplateHaskell #-}

import Control.Lens
import Control.Lens.Extras (is)

data NumCol = Empty |
              Single Int |
              Pair Int Int |
              Lots [Int]

-- Uses Template Haskell to create the Prisms _Empty, _Single, _Pair and _Lots
-- corresponding to your constructors
makePrisms ''NumCol

get_pairs :: [NumCol] -> [NumCol]
get_pairs = filter (is _Pair)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...