[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