public function bind($id, $concrete = null, $shared = false)
    {
        if (null === $concrete) {
            $concrete = $id;
        }

        $id = $this->normalizeString($id);

        //if its an instance save is as shared regardless of variable
        if (is_object($concrete) && !$concrete instanceof \Closure) {
            //apply any extenders - may not be that useful with an instance but hey ho.
            $instance = $this->applyExtenders($id, $concrete);
            $this->sharedInstances[$id] = $instance;
            return;
        }

        $concrete = $this->normalizeString($concrete);

        //if its callable, or is array and first item is callable
        if (is_callable($concrete) || (is_array($concrete) && is_callable($concrete[0]))) {
            if (false === $shared) {
                $this->definitions[$id] = (array) $concrete;
                return;
            }
            $this->sharedDefinitions[$id] = (array) $concrete;
            return;
        }

        //if its a class string and it exists, or its an array and the first item is a class string
        if (is_string($concrete) && class_exists($concrete) || (is_array($concrete) && class_exists($concrete[0]))) {
            if (false === $shared) {
                $this->definitions[$id] = (array) $concrete;
                return;
            }
            $this->sharedDefinitions[$id] = (array) $concrete;
            return;
        }

        //if were here its arbitary data to assign on the container
        $this->sharedInstances[$id] = $concrete;
    }