You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: values.go
    path of file: ./repos/gorgonia
    
    the code of the file until where you have to start completion: package gorgonia

import (
	"fmt"
	"unsafe"

	"github.com/chewxy/hm"
	"github.com/pkg/errors"
	"gorgonia.org/tensor"
)

// Value represents a value that Gorgonia accepts. At this point it is implemented by:
//		- all scalar value types (F64, F32... etc)
// 		- *tensor.Dense
// 		- *dualValue
//
// A Value is essentially any thing that knows its own type and shape.
// Most importantly though, a Value is a pointer - and can be converted into a tensor.Memory.
// This is done for the sake of interoperability with external devices like cgo or CUDA or OpenCL.
// This also means for the most part most Values will be alloc
    
func makeValue(t hm.Type, s tensor.Shape) (retVal Value, err error) {
	var dt tensor.Dtype
	if dt, err = dtypeOf(t); err != nil {
		return
	}

	if s.IsScalar() {
		switch dt {
		case tensor.Float64:
			return NewF64(0), nil
		case tensor.Float32:
			return NewF32(0), nil
		case tensor.Int:
			return NewI(0), nil
		case tensor.Int64:
			return NewI64(0), nil
		case tensor.Int32:
			return NewI32(0), nil
		case tensor.Byte:
			return NewU8(0), nil
		case tensor.Bool:
			return NewB(false), nil
		}
	}

	switch tt := t.(type) {
	case TensorType:
		return tensor.New(tensor.Of(dt), tensor.WithShape(s...)), nil
	default:
		err = errors.Errorf(nyiTypeFail, "MakeValue", tt)
		return
	}
}