Pattern Matching with Different Types

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Pattern Matching with Different Types

Yotam Ohad
Hello cafe,
I am trying to do the following:

data Foo = Foo { a1 :: Int -> Int, a2 :: Int -> Char }
data Bar = Bar { a1 :: Int -> Int }

func :: a -> Maybe (Int -> Int) -- a is either Foo or Bar
func (x::(Bar/Foo) = Just $ a1 x
func _ = Nothing

I'm not sure how to implement this. All I know that the types are matching so I think it could be possible.

Thanks for your help
-Yotam

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Pattern Matching with Different Types

Adam Bergmark-2
Hi Yotam,

One way to do this is to take an `Either Foo Bar` as an argument instead, then you can pattern match on its Left and Right. This is preferable if the function is only meant to work for a limited number of types. If you want it to be extensible to any number of types you can write a typeclass that contains `func` with the same type signature as you have now. There are also some extensions built in to GHC to do this automatically for you, but I don't recall exactly which ones to enable...

HTH,
Adam


On Tue, 10 Oct 2017 at 18:58 Yotam Ohad <[hidden email]> wrote:
Hello cafe,
I am trying to do the following:

data Foo = Foo { a1 :: Int -> Int, a2 :: Int -> Char }
data Bar = Bar { a1 :: Int -> Int }

func :: a -> Maybe (Int -> Int) -- a is either Foo or Bar
func (x::(Bar/Foo) = Just $ a1 x
func _ = Nothing

I'm not sure how to implement this. All I know that the types are matching so I think it could be possible.

Thanks for your help
-Yotam
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Pattern Matching with Different Types

Matt
In reply to this post by Yotam Ohad
Hi Yotam,

A type variable `a` means that you know absolutely nothing about the variable, and can't treat it specially. So you can't special-case your function to "either Foo or Bar."

You can achieve your goal like this:

func :: Either Foo Bar -> (Int -> Int)
func (Left (Foo a _)) = a
func (Right (Bar a)) = a


The kind of runtime type inspection you might be used to from other langauges is available via the Typeable class. It's extremely non-idiomatic Haskell, and I strongly recommend against writing this sort of code. For completeness, this also works:

func :: Typeable a => a -> Maybe (Int -> Int)
func a = maybeFoo <|> maybeBar
  where
    maybeFoo = case cast a of
      Just (Foo a _) -> Just a
      Nothing -> Nothing
    maybeBar = case cast a of
      Just (Bar a) -> Just a
      Nothing -> Nothing

Matt Parsons

On Tue, Oct 10, 2017 at 10:56 AM, Yotam Ohad <[hidden email]> wrote:
Hello cafe,
I am trying to do the following:

data Foo = Foo { a1 :: Int -> Int, a2 :: Int -> Char }
data Bar = Bar { a1 :: Int -> Int }

func :: a -> Maybe (Int -> Int) -- a is either Foo or Bar
func (x::(Bar/Foo) = Just $ a1 x
func _ = Nothing

I'm not sure how to implement this. All I know that the types are matching so I think it could be possible.

Thanks for your help
-Yotam

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.


_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Pattern Matching with Different Types

Eric Mertens
If you want a function's behavior to vary by the types at which it is used, you'd need to use a type class. For example:

data Foo = Foo { a1 :: Int -> Int, a2 :: Int -> Char }
data Bar = Bar { a3 :: Int -> Int }

class    Func a   where func :: a -> Maybe (Int -> Int)
instance Func Foo where func = Just . a1
instance Func Bar where func = Just . a3

On Tue, Oct 10, 2017 at 10:42 AM Matt <[hidden email]> wrote:
Hi Yotam,

A type variable `a` means that you know absolutely nothing about the variable, and can't treat it specially. So you can't special-case your function to "either Foo or Bar."

You can achieve your goal like this:

func :: Either Foo Bar -> (Int -> Int)
func (Left (Foo a _)) = a
func (Right (Bar a)) = a


The kind of runtime type inspection you might be used to from other langauges is available via the Typeable class. It's extremely non-idiomatic Haskell, and I strongly recommend against writing this sort of code. For completeness, this also works:

func :: Typeable a => a -> Maybe (Int -> Int)
func a = maybeFoo <|> maybeBar
  where
    maybeFoo = case cast a of
      Just (Foo a _) -> Just a
      Nothing -> Nothing
    maybeBar = case cast a of
      Just (Bar a) -> Just a
      Nothing -> Nothing

Matt Parsons

On Tue, Oct 10, 2017 at 10:56 AM, Yotam Ohad <[hidden email]> wrote:
Hello cafe,
I am trying to do the following:

data Foo = Foo { a1 :: Int -> Int, a2 :: Int -> Char }
data Bar = Bar { a1 :: Int -> Int }

func :: a -> Maybe (Int -> Int) -- a is either Foo or Bar
func (x::(Bar/Foo) = Just $ a1 x
func _ = Nothing

I'm not sure how to implement this. All I know that the types are matching so I think it could be possible.

Thanks for your help
-Yotam

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.