func (ns *NumberSet) CanContain(objType ObjectType) bool {
	return objType == ObjectTypeNumber || objType == ObjectTypeNumberSet
}
CanContain whether or not the number set can contain the objType
package language
import (
	"bytes"
	"fmt"
	"sort"
	"strconv"
	"strings"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/dynamodb"
)
var (
	NULL = &Null{}
	TRUE = &Boolean{Value: true}
	FALSE = &Boolean{Value: false}
)
type ObjectType string
const (
	ObjectTypeBinary ObjectType = "B"
	ObjectTypeBinarySet ObjectType = "BS"
	ObjectTypeBoolean ObjectType = "BOOL"
	ObjectTypeList ObjectType = "L"
	ObjectTypeMap ObjectType = "M"
	ObjectTypeNull ObjectType = "NULL"
	ObjectTypeNumber ObjectType = "N"
	ObjectTypeNumberSet ObjectType = "NS"
	ObjectTypeStringSet ObjectType = "SS"
	ObjectTypeString ObjectType = "S"
	ObjectTypeError ObjectType = "ERR"
	ObjectTypeFunction ObjectType = "FN"
)
var dynamodbTypes = map[ObjectType]bool{
	ObjectTypeBinary:    true,
	ObjectTypeBinarySet: true,
	ObjectTypeBoolean:   true,
	ObjectTypeList:      true,
	ObjectTypeMap:       true,
	ObjectTypeNull:      true,
	ObjectTypeNumber:    true,
	ObjectTypeNumberSet: true,
	ObjectTypeStringSet: true,
	ObjectTypeString:    true,
}
var comparableTypes = map[ObjectType]bool{
	ObjectTypeNumber: true,
	ObjectTypeString: true,
	ObjectTypeBinary: true,
}
var setTypes = map[ObjectType]bool{
	ObjectTypeBinarySet: true,
	ObjectTypeStringSet: true,
	ObjectTypeNumberSet: true,
}
type Object interface {
	Type() ObjectType
	Inspect() string
	ToDynamoDB() *dynamodb.AttributeValue
}
type ContainerObject interface {
	Object
	Contains(obj Object) bool
	CanContain(objType ObjectType) bool
}
type Number struct {
	Value float64
}
func (i *Number) Inspect() string {
	return numToString(i.Value)
}
func (i *Number) Type() ObjectType {
	return ObjectTypeNumber
}
func (i *Number) ToDynamoDB() *dynamodb.AttributeValue {
	str := numToString(i.Value)
	return &dynamodb.AttributeValue{N: &str}
}
func numToString(v float64) string {
	return strconv.FormatFloat(v, 'f', -1, 64)
}
type Boolean struct {
	Value bool
}
func (b *Boolean) Inspect() string {
	return fmt.Sprintf("%t", b.Value)
}
func (b *Boolean) Type() ObjectType {
	return ObjectTypeBoolean
}
func (b *Boolean) ToDynamoDB() *dynamodb.AttributeValue {
	return &dynamodb.AttributeValue{BOOL: aws.Bool(b.Value)}
}
func nativeBoolToBooleanObject(input bool) *Boolean {
	if input {
		return TRUE
	}
	return FALSE
}
type Binary struct {
	Value []byte
}
func (b *Binary) Inspect() string {
	return fmt.Sprintf("%v", b.Value)
}
func (b *Binary) Type() ObjectType {
	return ObjectTypeBinary
}
func (b *Binary) ToDynamoDB() *dynamodb.AttributeValue {
	return &dynamodb.AttributeValue{B: b.Value}
}
func (b *Binary) Contains(obj Object) bool {
	bin, ok := obj.(*Binary)
	if !ok {
		return false
	}
	return bytes.Contains(b.Value, bin.Value)
}
func (b *Binary) CanContain(objType ObjectType) bool {
	return objType == ObjectTypeBinary
}
type Null struct{}
func (n *Null) Type() ObjectType { return ObjectTypeNull }
func (n *Null) Inspect() string {
	return "null"
}
func (n *Null) ToDynamoDB() *dynamodb.AttributeValue {
	return &dynamodb.AttributeValue{NULL: aws.Bool(true)}
}
type Error struct {
	Message string
}
func (e *Error) Type() ObjectType { return ObjectTypeError }
func (e *Error) Inspect() string { return "ERROR: " + e.Message }
func (e *Error) ToDynamoDB() *dynamodb.AttributeValue {
	return nil
}
type String struct {
	Value string
}
func (s *String) Inspect() string {
	return s.Value
}
func (s *String) Type() ObjectType {
	return ObjectTypeString
}
func (s *String) Contains(obj Object) bool {
	str, ok := obj.(*String)
	if !ok {
		return false
	}
	return strings.Contains(s.Value, str.Value)
}
func (s *String) ToDynamoDB() *dynamodb.AttributeValue {
	return &dynamodb.AttributeValue{S: aws.String(s.Value)}
}
func (s *String) CanContain(objType ObjectType) bool {
	return objType == ObjectTypeString
}
type Map struct {
	Value map[string]Object
}
func (m *Map) Inspect() string {
	var out bytes.Buffer
	out.WriteString("{")
	for k, obj := range m.Value {
		out.WriteString("\n  \"")
		out.WriteString(k)
		out.WriteString("\" : ")
		out.WriteString(obj.Inspect())
		out.WriteString("<")
		out.WriteString(string(obj.Type()))
		out.WriteString(">,\n")
	}
	out.WriteString("}")
	return out.String()
}
func (m *Map) Type() ObjectType {
	return ObjectTypeMap
}
func (m *Map) ToDynamoDB() *dynamodb.AttributeValue {
	attr := &dynamodb.AttributeValue{M: map[string]*dynamodb.AttributeValue{}}
	for k, v := range m.Value {
		attr.M[k] = v.ToDynamoDB()
	}
	return attr
}
func (m *Map) Get(field string) Object {
	obj, ok := m.Value[field]
	if !ok {
		return NULL
	}
	return obj
}
type List struct {
	Value []Object
}
func (l *List) Inspect() string {
	var out bytes.Buffer
	out.WriteString("[ ")
	for _, obj := range l.Value {
		out.WriteString(obj.Inspect())
		out.WriteString("<")
		out.WriteString(string(obj.Type()))
		out.WriteString("> ")
	}
	out.WriteString("]")
	return out.String()
}
func (l *List) Type() ObjectType {
	return ObjectTypeList
}
func (l *List) ToDynamoDB() *dynamodb.AttributeValue {
	attr := &dynamodb.AttributeValue{L: []*dynamodb.AttributeValue{}}
	for _, v := range l.Value {
		attr.L = append(attr.L, v.ToDynamoDB())
	}
	return attr
}
func (l *List) Get(position int64) Object {
	obj := l.Value[position]
	if obj == nil {
		return NULL
	}
	return obj
}
func (l *List) Contains(obj Object) bool {
	if !l.CanContain(obj.Type()) {
		return false
	}
	for _, e := range l.Value {
		if equalObject(obj, e) {
			return true
		}
	}
	return false
}
func (l *List) CanContain(objType ObjectType) bool {
	return !(objType == ObjectTypeList || objType == ObjectTypeMap || setTypes[objType])
}
type StringSet struct {
	Value map[string]bool
}
func (ss *StringSet) Inspect() string {
	var out bytes.Buffer
	vals := make([]string, 0, len(ss.Value))
	for v := range ss.Value {
		vals = append(vals, v)
	}
	sort.Strings(vals)
	out.WriteString("[ ")
	for _, k := range vals {
		out.WriteString(k)
		out.WriteString(" ")
	}
	out.WriteString("]<SS>")
	return out.String()
}
func (ss *StringSet) Type() ObjectType {
	return ObjectTypeStringSet
}
func (ss *StringSet) Contains(obj Object) bool {
	if obj.Type() == ObjectTypeStringSet {
		ssInput, ok := obj.(*StringSet)
		if !ok {
			return false
		}
		for str := range ssInput.Value {
			if !ss.Value[str] {
				return false
			}
		}
		return true
	}
	str, ok := obj.(*String)
	if !ok {
		return false
	}
	return ss.Value[str.Value]
}
func (ss *StringSet) ToDynamoDB() *dynamodb.AttributeValue {
	attr := &dynamodb.AttributeValue{SS: make([]*string, 0, len(ss.Value))}
	for v := range ss.Value {
		attr.SS = append(attr.SS, aws.String(v))
	}
	return attr
}
func (ss *StringSet) CanContain(objType ObjectType) bool {
	return objType == ObjectTypeString || objType == ObjectTypeStringSet
}
type BinarySet struct {
	Value [][]byte
}
func (bs *BinarySet) Inspect() string {
	var out bytes.Buffer
	out.WriteString("[ ")
	for _, k := range bs.Value {
		out.WriteString(fmt.Sprintf("%v", k))
		out.WriteString(" ")
	}
	out.WriteString("]<BS>")
	return out.String()
}
func (bs *BinarySet) Type() ObjectType {
	return ObjectTypeBinarySet
}
func containedInBinaryArray(container [][]byte, bin []byte) bool {
	for _, b := range container {
		if bytes.Equal(b, bin) {
			return true
		}
	}
	return false
}
func (bs *BinarySet) ToDynamoDB() *dynamodb.AttributeValue {
	return &dynamodb.AttributeValue{BS: bs.Value}
}
func (bs *BinarySet) Contains(obj Object) bool {
	if obj.Type() == ObjectTypeBinarySet {
		bsInput, ok := obj.(*BinarySet)
		if !ok {
			return false
		}
		for _, bin := range bsInput.Value {
			if !containedInBinaryArray(bs.Value, bin) {
				return false
			}
		}
		return true
	}
	bin, ok := obj.(*Binary)
	if !ok {
		return false
	}
	return containedInBinaryArray(bs.Value, bin.Value)
}
func (bs *BinarySet) CanContain(objType ObjectType) bool {
	return objType == ObjectTypeBinary || objType == ObjectTypeBinarySet
}
type NumberSet struct {
	Value map[float64]bool
}
func (ns *NumberSet) Inspect() string {
	var out bytes.Buffer
	vals := make([]float64, 0, len(ns.Value))
	for v := range ns.Value {
		vals = append(vals, v)
	}
	sort.Float64s(vals)
	out.WriteString("[ ")
	for _, k := range vals {
		out.WriteString(fmt.Sprintf("%v", k))
		out.WriteString(" ")
	}
	out.WriteString("]<NS>")
	return out.String()
}
func (ns *NumberSet) Type() ObjectType {
	return ObjectTypeNumberSet
}
func (ns *NumberSet) ToDynamoDB() *dynamodb.AttributeValue {
	attr := &dynamodb.AttributeValue{NS: make([]*string, 0, len(ns.Value))}
	for v := range ns.Value {
		str := numToString(v)
		attr.NS = append(attr.NS, &str)
	}
	return attr
}
func (ns *NumberSet) Contains(obj Object) bool {
	if obj.Type() == ObjectTypeNumberSet {
		nsInput, ok := obj.(*NumberSet)
		if !ok {
			return false
		}
		for str := range nsInput.Value {
			if !ns.Value[str] {
				return false
			}
		}
		return true
	}
	n, ok := obj.(*Number)
	if !ok {
		return false
	}
	return ns.Value[n.Value]
}