
Andrew U. Frank wrote:
I have a number of functions which have some arguments and produce a single result. all the arguments are in a heterogenous list and the results should update the list.
If I understand the problem correctly, you have a typed-indexed collection TIP and you would like to apply a transformation function to it, whose argument types and the result type are in the TIP. The function should locate its arguments based on their types, and update the TIP with the result. The function may have any number of arguments, including zero; the order of arguments should not matter. Then the following code seems to solve the problem. It starts with the examples. {-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-} {-# LANGUAGE ScopedTypeVariables, UndecidableInstances #-} -- Transforming a TIP: applying to a TIP a (polyvariadic) function -- that takes arguments from a TIP and updates the TIP with the result module TIPTransform where import Data.HList import Data.HList.TIP import Data.HList.TypeEqGeneric1 import Data.HList.TypeCastGeneric1 import Data.HList.Label5 newtype MyVal = MyVal Int deriving Show -- A sample TIP tip1 = MyVal 20 .*. (1::Int) .*. True .*. emptyTIP -- TIP (HCons (MyVal 20) (HCons 1 (HCons True HNil))) -- Update the Int component of tip1 to 2. The Int component must -- exist. Otherwise, it is a type error tip2 = ttip (2::Int) tip1 -- TIP (HCons (MyVal 20) (HCons 2 (HCons True HNil))) -- Negate the boolean component of tip1 tip3 = ttip not tip1 -- TIP (HCons (MyVal 20) (HCons 1 (HCons False HNil))) -- Update the Int component from the values of two other components tip4 = ttip (\(MyVal x) y -> x+y) tip1 -- TIP (HCons (MyVal 20) (HCons 21 (HCons True HNil))) -- Update the MyVal component from the values of three other components tip5 = ttip (\b (MyVal x) y -> MyVal $ if b then x+y else 0) tip1 -- TIP (HCons (MyVal 21) (HCons 1 (HCons True HNil))) -- The same but with the permuted argument order. -- The order of arguments is immaterial: the values will be looked up using -- their types tip5' = ttip (\b y (MyVal x)-> MyVal $ if b then x+y else 0) tip1 -- TIP (HCons (MyVal 21) (HCons 1 (HCons True HNil))) -- The implementation class TransTIP op db where ttip :: op -> db -> db instance (HMember op db b, TransTIP' b op (TIP db)) => TransTIP op (TIP db) where ttip = ttip' (undefined::b) class TransTIP' b op db where ttip' :: b -> op -> db -> db -- If op is found in a TIP, update the TIP with op instance (HTypeIndexed db, HUpdateAtHNat n op db db, HType2HNat op db n) => TransTIP' HTrue op (TIP db) where ttip' _ = tipyUpdate -- If op is not found in a TIP, it must be a function. Look up -- its argument in a TIP and recur. instance (HOccurs arg db, TransTIP op db) => TransTIP' HFalse (arg -> op) db where ttip' _ f db = ttip (f (hOccurs db)) db