简体   繁体   中英

Is it possible in Haskell to write the catch-all pattern first? Or use “negative” pattern?

Sometimes, if one the pattern rules need some special rhs which is made more readable via where , I end up with something like this

data D = A | B | C
func :: D -> b
func A = special_case
  where
    special_case = other helper
    other = aaaa
    helper = bbb
func _ = bla

where the catch-all pattern seems to be so far from the other pattern, because of the lengthy where . It'd be nice if I could write something like this:

func :: D -> b
func !A = bla -- imaginary syntax
func A = special_case
  where
    special_case = other helper
    other = aaaa
    helper = bbb

I don't think it would still be called catch-all, but rather "catch-all-but", but is there any way to do this?

If you don't need to bind anything, you could do something like this:

isA :: D -> Bool
isA A = True
isA _ = False

func :: D -> b
func d | not (isA d) = bla
func A = special_case where ...

(You could alternately implement isn'tA to avoid the not . But while I've seen functions like isA defined every so often, I don't believe I've ever seen an analog of isn'tA in the wild.)

It might not be obvious to the compiler that this match is complete. You could fix that like this:

type A'sFields = () -- your specific D doesn't have any fields for A,
                    -- but this pattern is general enough to use for
                    -- constructors that do

fromA :: D -> Maybe A'sFields
fromA A = Just ()
fromA _ = Nothing

func :: D -> b
func d = case fromA d of
    Nothing -> bla
    Just () -> special_case where ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM