[Haskell-beginners] Writing a polymorphic function in Haskell

Matt Williams matt.williams45.mw at gmail.com
Sat Sep 23 15:17:25 UTC 2017


Dear All,

Thanks so much for your help. It was largely a syntactic issue around
pattern matching - but I also learnt about the @ operator for
patter-matching.

The correct code is posted below in case it helps anyone else. The only
other think would be to rewrite eviCheck as an inline function using where,
but I am happy with this for now.

Thanks for your speedy help.

BW,
Matt

checkConflict3 :: Arg -> Arg -> Bool
checkConflict3 (IndArg _ at1 at2 _ adir) (IndArg _ bt1 bt2 _ bdir) =
    if at1 == bt1 && at2 == bt2 && adir /= bdir then True
    else if at1 == bt2 && at2 == bt1 && revDir (adir) /= bdir then True
    else False
checkConflict3 (IndArg e _ _ _ _)  (MetaArg a) = eviCheck e a
checkConflict3 a@(MetaArg a) b@(IndArg e _ _ _ _) = eviCheck b a
checkConflict3 (MetaArg _) (MetaArg _) = False
checkConflict3 _ _ = False --A final catchall

eviCheck:: Evi -> EviType -> Bool
eviCheck (SimpEvi  _ _ _ _ type1) type2 =  if type1 == type2 then True
    else False

On 22 September 2017 at 21:16, David McBride <toad3k at gmail.com> wrote:

> It is a mistake to use record syntax with data types with multiple
> constructors.  It creates a partial function that dies when you try to
> use it on a constructor that does not have that field.  It is a flaw
> in the language that many people would like to see removed because it
> allows programs to compile that will fail at run time, possibly
> unexpectedly.
>
> Arg can have a constructor that does not have an evi.  Also what
> happens if you compare an IndArg to a MetaArg?  Or a MetaArg to
> another MetaArg?
>
> You should remove all of these record names, and then write
> checkConflict as follows (warning untested):
>
> checkConflict :: Arg -> Arg -> Bool
> checkConflict (IndArg _ at1 at2 _ adir) (IndArg _ bt1 bt2 _ bdir) =
> at1 == bt1 && at2 == bt2 && adir /= bdir
> -- checkConflict (IndArg ...) (MetaArg) = ???
> -- checkConflict a@(MetaArg ...) b@(IndArg ...) = checkConflict b a
> -- checkConflict (MetaArg _) (MetaArg _) = ???
> checkConflict _ _ -> False -- perhaps a catchall?
>
> However, you may keep the records as long as you are absolutely sure
> you are using them only in places where you have the appropriate
> constructor.
>
> On Fri, Sep 22, 2017 at 3:53 PM, Matt Williams
> <matt.williams45.mw at gmail.com> wrote:
> > Dear All,
> >
> > I am having problems writing a polymorphic function.
> >
> > I have a type that has two constructors:
> >
> > data Arg = IndArg {evi::Evi, t1::Treatment, t2::Treatment, out::Outcome,
> > dir::Direction}
> >             | MetaArg {target::EviType}
> >             deriving (Show)
> >
> > I have a function checks for conflict:
> >
> > checkConflict :: Arg -> Arg -> Bool
> > checkConflict a b = if t1 a == t1 b && t2 a == t2 b && dir a /= dir b
> then
> > True
> >                      else False
> >
> > However, I can't make this work with both types of Argument - if I pass
> it
> > MetaArg, it raises an error.
> >
> > In another language, I would write something like:
> >
> > checkConflict(ArgA,ArgB):
> >
> >
> >
> > _______________________________________________
> > Beginners mailing list
> > Beginners at haskell.org
> > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
> >
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org
> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/beginners/attachments/20170923/bef33b54/attachment.html>


More information about the Beginners mailing list