# Tensors

To get the most out of the walkthrough, we encourage you to follow along with the examples in a GHCi session.

To start, import `Torch`

:

```
import Torch
```

A `Tensor`

in Hasktorch is multidimensional array with a fixed shape
and element type.

For example, we can initialize a tensor with shape `[3, 4]`

and filled
with zeros using

```
zeros' ([3, 4] :: [Int]) =>
Tensor Float [3,4] [[ 0.0000, 0.0000, 0.0000, 0.0000],
[ 0.0000, 0.0000, 0.0000, 0.0000],
[ 0.0000, 0.0000, 0.0000, 0.0000]]
```

We can also initialize a tensor from a Haskell list using `asTensor`

:

```
asTensor ([[4, 3], [2, 1]] :: [[Float]]) =>
Tensor Float [2,2] [[ 4.0000 , 3.0000 ],
[ 2.0000 , 1.0000 ]]
```

Note that the numerical type of the tensor is inferred from the types of the values in the list.

Scalar values are represented in Hasktorch as tensors with shape `[]`

:

```
asTensor (3.5 :: Float) =>
Tensor Float [] 3.5000
```

We can get the scalar value back out using `asValue`

:

```
asValue (asTensor (3.5 :: Float)) :: Float =>
3.5
```

## Specifying Tensor parameters

In the previous section we initialized a tensor filled with zeros using
`zeros'`

(note the prime suffix). Hasktorch functions use a convention
where default versions of functions use a prime suffix. The unprimed
versions of these functions expect an additional parameter specifying
tensor parameters. For example:

```
zeros :: [Int] -> Torch.TensorOptions -> Tensor
```

`TensorOptions`

are typically specified by starting with
`Torch.TensorOptions.defaultOpts`

and modifying using one or more of
the following:

`withDType`

configures the data type of the elements`withDevice`

configures on which device the tensor is to be usedothers (see

`Torch.TensorOptions`

)

For example, to construct a matrix filled with zeros of dtype `Int64`

:

```
zeros [4, 4] (withDType Int64 defaultOpts) =>
Tensor Int64 [4,4] [[ 0, 0, 0, 0],
[ 0, 0, 0, 0],
[ 0, 0, 0, 0],
[ 0, 0, 0, 0]]
```

## Tensor factories

Hasktorch comes with many "factory" functions similar to `zeros`

and
`zeros'`

useful for initializing common kinds of tensors. For example,
`ones`

, `full`

, `eye`

, and the primed versions of these. See the
`Torch.TensorFactories`

module for a complete list.

One useful class of factory functions are those suffixed with "-like"
(e.g. `onesLike`

), which initialize a tensor
with the same dimensions as their argument. For example:

```
let x = zeros' [3, 2] in onesLike x =>
Tensor Float [3,2] [[ 1.0000 , 1.0000 ],
[ 1.0000 , 1.0000 ],
[ 1.0000 , 1.0000 ]]
```

## Operations

Most operations are pure functions, similar to Haskell standard library math operations.

Tensors implement the `Num`

typeclass, meaning they support the usual
arithmetic operations:

```
let x = ones' [4] in x + x =>
Tensor Float [4] [ 2.0000 , 2.0000 , 2.0000 , 2.0000 ]
```

Some operations transform a tensor:

```
relu (asTensor ([-1.0, -0.5, 0.5, 1] :: [Float])) =>
Tensor Float [4] [ 0.0000, 0.0000, 0.5000 , 1.0000 ]
```

`Torch.Tensor.select`

slices out a selection by specifying a dimension
and index:

```
let x = asTensor ([[[1, 2, 3]], [[4, 5, 6]], [[7, 8, 9]], [[10, 11, 12]]] :: [[[Int]]])
```

```
shape x =>
[4,1,3]
```

```
select 2 1 x =>
Tensor Int64 [4,1] [[ 2],
[ 5],
[ 8],
[ 11]]
```

```
let y = asTensor ([1, 2, 3] :: [Int])
```

```
select 0 1 y =>
Tensor Int64 [] 2
```

Values can be extracted from a tensor using `asValue`

so long as the
dtype matches the Haskell type:

```
let x = asTensor ([2] :: [Int]); y = asValue x :: Int in y =>
2
```