Procedure Proc(Array a(1), List l(), Map m())
If IsArray(a())
; This code will be executed if the Array is valid.
EndIf
If IsList(l())
; This code will be executed if the List is valid.
EndIf
If IsMap(m())
; This code will be executed if the Map is valid.
EndIf
EndProcedure
Proc(0, 0, 0)
Wouldn't ArraySize(), ListSize(), and MapSize() be good enough to detect if they've been used? ArraySize() returns -1 if the array doesn't exist, so that'll definitely work; and ListSize() and MapSize() both return 0 if they don't contain any elements. But I don't know what your code is doing, so maybe they're not the solution you're looking for.
We have a pointer and a type (array, list, map) of how the pointer relates to the data. That is, we ourselves give the type. If you need to check the type, then the data must contain at the beginning the data bytes (1, 2, 3), which determines what the data is. Someone will break the program if he tried to access the data directly. For example, the Arr.s{1}(5) array will contain 6 elements one after the other, one character at a time, and you can take the data by pointer with a shift. If you add a flag to the beginning of the array that defines the data, then accessing the pointer with a shift will be broken.