Deriving Generic Functions by Example Neil Mitchell www.cs.york.ac.uk/~ndm/derive
“Generic” Functions � Operates on many data types � Think of equality � Comparing two integers, booleans, lists, trees � Usually, must give each version separately � True in Ada, Java, Haskell... � But usually they follow a pattern!
Cons 1 ( Cons 2 ( Cons 3 Ni l ) ) dat a Li st = Cons I nt Li st A Haskell data type 3 | Ni l 2 dat a 1
Generic Equality on Lists i nst ance i nst ance Eq Li st wher e wher e Cons a b ≡ Cons x y = a ≡ x ∧ b ≡ y Ni l ≡ Ni l = Tr ue _ ≡ _ = Fal se They have the same constructor 1. All fields are equal 2.
Generic Equality on Trees dat a dat a Tr ee = B Tr ee I nt Tr ee | L i nst ance i nst ance Eq Tr ee wher e wher e B a b c ≡ B x y z = a ≡ x ∧ b ≡ y ∧ c ≡ z L ≡ L = Tr ue _ ≡ _ = Fal se
Generic Equality on anything? � Always follows the same simple pattern � But highly dependent on the data type � If data type changes, updates required � Could “miss” a field doing it by hand � Solution: Have it automatically generated � The DrIFT and Derive tools allows this
The Problem � Need to state to the computer the relationship between data and code � Must be 100% precise � I explained mainly through examples � Requires learning an API, working at a meta-level, testing etc.
Specifying the Relationship Dat aType → St r i ng eq' dat = si m pl e_i nst ance " Eq" dat [ f unN " ==" body] wher e wher e body = m ap r ul e ( dat aCt or s dat ) ++ [ def cl ause 2 f al se] r ul e ct or = scl ause [ ct p ct or ' a' , ct p ct or ' b' ] ( and_ ( zi pW i t h ( ==: ) ( ct v ct or ' a' ) ( ct v ct or ' b' ) ) ) YUK!
Generic Functions by Example � What if we provide only an example � The computer can infer the rules � Uses concepts the user understands � Guaranteed to work on at least 1 example � Guaranteed to be type correct � Quicker to write
Giving an example � Needs to be on an interesting data type � Complex enough to have variety dat a dat a Dat aNam e = Fi r st | Second Any | Thi r d Any Any | Four t h Any Any
And the example… i nst ance Eq Dat aNam i nst ance e wher e wher e ≡ Fi r st Fi r st = Tr ue ≡ Second y 1 = x 1 ≡ y 1 ∧ Tr ue Second x 1 x 1 x 2 ≡ Thi r d y 1 y 2 = x 1 ≡ y 1 ∧ x 2 ≡ y 2 ∧ Tr ue Thi r d Four t h x 1 x 2 ≡ Four t h y 1 y 2 = x 1 ≡ y 1 ∧ x 2 ≡ y 2 ∧ Tr ue _ ≡ _ = Fal se Now y 1 and y 2 Redundant True instead of x and y at the end
Notation for Substitution York ⇒ Hello [#] Hello York Tom ⇒ Hello [#] Hello Tom YDS ⇒ [date] 2007/10/26 Parameter Substitute
Assign Parameters Idea: Move from the specific example, to a generalised version Thi r d y 1 y 2 3 rd constructor 1 ⇒ y[#] 2 ⇒ y[#] ⇒ [name]
Group lists (M AP ) Only if: 1. Consecutive parameters 1 ⇒ y[#] 2 ⇒ y[#] 2. Same generator Thi r d y 1 y 2 3 rd constructor 2 ⇒ M AP 1..# y[#] ⇒ [name]
The meaning of M AP • 2 ⇒ M AP 1..# y[#] • M AP 1..2 y[#] • (1 ⇒ y[#]) (2 ⇒ y[#]) • y 1 y 2
Generalise Numbers 2 ⇒ M AP 1..# y[#] Thi r d y 1 y 2 3 rd constructor 3 rd constructor ⇒ [name] ⇒ M AP 1..arity y[#]
Combine elements 3 rd constructor 3 rd constructor ⇒ M AP 1..arity y[#] ⇒ [name] Thi r d y 1 y 2 3 rd constructor ⇒ [name] (M AP 1..arity y[#])
Applying to other constructors 3 rd constructor ⇒ [name] (M AP 1..arity y[#]) Fi r st Fi r st Second Second y 1 Thi r d Thi r d y 1 y 2 Four t h Four t h y 1 y 2
The Complete Generalisation i nst ance i nst ance Eq [ dat anam e] wher e wher e [ M AP ct or s ( AP 1. . ar i t y ( x[ #] ) ) ≡ ( [ nam e] [ M ( [ nam e] [ M AP 1. . ar i t y ( y[ #] ) ) = LDR ( ∧ ) Tr ue [ F O AP 1. . ar i t y ( x[ #] ≡ y[ #] ) ] [ M ] ) ] _ ≡ _ = Fal se
Limitations: Non-inductive � Example: Binary serialisation � Write out a tag (which constructor) then the fields � If only one constructor, no need for a tag � There is no general pattern
Limitations: Type Based � Example: Monoid � The instance for a Monoid is based on the types of the fields � Equal types have one value, different another � The DataName type does not have different types
Limitations: Records � Example: Show dat a Pai r = Pai r { f st : : I nt , snd: : I nt } show ( Pai r 1 2) = “ Pai r { f st =1, snd=2} ” � Show includes the record field names � DataName does not have record fields
Success Failure 15 9 Success Rate •Arbitrary •Enum •Serial •Data •Ord •Eq •…
Future Work � Extend the data type with more variety � Allows more classes to be specified � But more work to specify each class � New uses for the information � Can derive classes at runtime � Implement in other languages (Java?)
Conclusion � Writing generic functions is cumbersome � Writing generic relationships is hard � Writing a single example is much easier � Works well in practice � Enables new contributors
x 1 ≡ y 1 ∧ x 2 ≡ y 2 ∧ Tr ue ⇒ True 2 ⇒ x[#] ≡ y[#] 1 ⇒ y[#] Example 2 1 ⇒ x[#] ≡ y[#] 1 ⇒ x[#]
Generalising to a F OLDR 1 ⇒ x[#] ≡ y[#] 2 ⇒ x[#] ≡ y[#] ⇒ True x 1 ≡ y 1 ∧ x 2 ≡ y 2 ∧ Tr ue F OLDR ( ∧ ) True (1 ⇒ x[#] ≡ y[#], 2 ⇒ x[#] ≡ y[#])
Generalising to a M AP F OLDR ( ∧ ) True (1 ⇒ x[#] ≡ y[#], 2 ⇒ x[#] ≡ y[#]) x 1 ≡ y 1 ∧ x 2 ≡ y 2 ∧ Tr ue 2 ⇒ F OLDR ( ∧ ) True (M AP 1..# (x[#] ≡ y[#]))
Recommend
More recommend