Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

23: Modules, overloaded functions and generic functions

E2301

No .ss file for an import. import name looks for name.ss next to the importing file, then in each folder of the Python path.

import attentoin

Check the name, or put the folder that has the file on the Python path. See Importing other files.

E2302

Files that import each other. A file can’t import itself, directly or through other files: each file is checked with what it imports, so a cycle has nowhere to start.

$ cat a.ss
import b
$ cat b.ss
import a
$ shapescript check a.ss
error[E2302]: `b.ss` imports this file back
  = note: the files import each other: a.ss -> b.ss -> a.ss

Move what both need into a third file that both import. See Importing other files.

E2303

An imported file has errors. A file is checked with the files it imports, and an error in one of them is reported at the import that leads to it, with its errors as notes.

$ cat broken.ss
fn f(x: [n]) -> [n] = y
$ cat main.ss
import broken
$ shapescript check main.ss
error[E2303]: `broken.ss` has an error
  = note: broken.ss:1:23: error[E0301]: unknown name `y`

Fix the imported file; shapescript check on it shows the errors in full. See Importing other files.

E2304

A name an imported file doesn’t declare. std.name must be declared at the top level of the file imported as std.

import shapescript.std.fit as std

fn f(x: [n]) -> [n] = std.nothing(x)

Check the spelling, and that the declaration is in that file, not in one it imports: a file’s own imports aren’t part of its names. See Importing other files.

E2305

Standalone build of a file with imports. A --standalone module needs only torch, but it would import the other files through the shapescript package’s import hook.

$ cat main.ss
import shapescript.std.fit as std
$ shapescript build --standalone --devices cpu main.ss
error[E2305]: a standalone build can't import other `.ss` files

Build without --standalone, or put what you import into the file. See Importing other files.

E2306

An import or generic function where it can’t be used. Importing other .ss files, and calling generic functions, work in files, not in notebook cells; a program on several devices can’t import them yet, since each device’s worker runs only the file’s own code; an exported program can’t call another file’s functions; and an imported file can’t declare other devices than the file importing it.

%%shapescript
import layers
error[E2306]: `import` of a `.ss` file can't be used here

Put what you import into the cell or the file. See Importing other files.

E2307

Functions of the same name for the same model. Functions may share a name only when each takes a different model as its first parameter, since a call picks one by its first argument’s model.

dim D = 4

model A:
    param w: [D] = zeros

fn forward(m: A, x: [D]) -> [D] = x * m.w

fn forward(m: A, x: [D]) -> [D] = x + m.w

Rename one of them. A function whose first parameter isn’t a model, and a generic function, can’t share their names. See Overloaded functions.

E2308

No function of that name for the argument’s model. Each function of the name takes a model first, and none takes the first argument’s.

dim D = 4

model A:
    param w: [D] = zeros

model B:
    param v: [D] = zeros

model Z:
    param z: [D] = zeros

fn forward(m: A, x: [D]) -> [D] = x * m.w

fn forward(m: B, x: [D]) -> [D] = x + m.v

fn f(z: Z, x: [D]) -> [D] = forward(z, x)

Declare a forward for Z, in this file or in the one that declares Z. See Overloaded functions.

E2309

Misused type variable. A type variable of a generic function can’t also name an axis of its signature, and it must be used by a parameter, since calls work it out from their arguments.

dim D = 4

fn f(m: M, x: [M D]) -> [D] = x[0]

Use another letter for the axis, or a name, such as n. See Generic functions.

E2310

Arguments disagree about a type variable. Each type variable stands for one type in a call, worked out from the arguments: two arguments that make it different types, or no argument that says what it is, are an error.

dim D = 4

model A:
    param w: [D] = zeros

model B:
    param v: [D] = zeros

fn same(a: M, b: M) -> [D] = zeros_like(a)

fn f(a: A, b: B) -> [D] = same(a, b)

Pass values of the same type, or give the function two type variables, as fn same(a: M, b: N). A value from Python has no ShapeScript type to give. See Generic functions.

E2311

A generic function needs a function the model doesn’t have. A generic function’s instance for a model calls a function on it that isn’t declared for that model, in the generic function’s file or the model’s. The error is at the call to the generic function, and names where it uses the function.

import shapescript.std.fit as std

dim D = 4

model Plain:
    param w: [D] = zeros

data Ex:
    x: [D]

fn train(mut m: Plain, data: Dataset[Ex], sink: LogSink, mode: Mode):
    std.fit(mut m, data, sink, 1, 8, 0.1, mode)
error[E2311]: `fit` with M = Plain, E = Ex needs a function `loss` that takes `Plain` first
  = note: `train_step` uses it at <shapescript>/std/fit.ss:29:27, called by `run` …

Declare it, here fn loss(m: Plain, batch: [b] Ex, mode: Mode) -> [], next to the model. See Generic functions.

E2312

A generic function doesn’t check with these types. Checking the instance of a generic function for the types of a call found an error. The error is at the call, with the error in the generic function as a note.

dim D = 4

model A:
    param w: [D] = zeros

fn loss(m: A) -> [D] = m.w

fn grad_of(m: M) -> Grad[M]:
    l, g = value_and_grad(loss, m)
    return g

fn f(m: A) -> Grad[A] = grad_of(m)

Here loss for A doesn’t give a [], so it can’t be differentiated. Change the function for the type, or call the generic function with another. See Generic functions.

E2313

Generic functions call each other too deeply. Each level of generic functions that call others for new types makes a round of new instances, and there may be 16.

dim D = 4

model A:
    param w: [D] = zeros

fn g1(m: M) -> [D] = g2(m)
fn g2(m: M) -> [D] = g3(m)
fn g3(m: M) -> [D] = g4(m)
fn g4(m: M) -> [D] = g5(m)
fn g5(m: M) -> [D] = g6(m)
fn g6(m: M) -> [D] = g7(m)
fn g7(m: M) -> [D] = g8(m)
fn g8(m: M) -> [D] = g9(m)
fn g9(m: M) -> [D] = g10(m)
fn g10(m: M) -> [D] = g11(m)
fn g11(m: M) -> [D] = g12(m)
fn g12(m: M) -> [D] = g13(m)
fn g13(m: M) -> [D] = g14(m)
fn g14(m: M) -> [D] = g15(m)
fn g15(m: M) -> [D] = g16(m)
fn g16(m: M) -> [D] = g17(m)
fn g17(m: M) -> [D] = g18(m)
fn g18(m: M) -> [D] = m.w

fn f(a: A) -> [D] = g1(a)

Make the chain shorter, or make some of its functions take the concrete type. See Generic functions.