[Haskell-cafe] Re: retrieving arguments for functions from a heterogenous list

oleg at okmij.org oleg at okmij.org
Wed Sep 16 02:58:39 EDT 2009

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

{-# 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

More information about the Haskell-Cafe mailing list