Понимание ошибки типа: “контрольная сигнатура Int*Int-> Интервал, но получила Int*Int-> Интервал”

Предлагаю создать завод по производству двигателей. Помните принцип « Одиночной ответственности » ( ТВЕРДЫЙ ).

В реальной жизни вы не строите двигатель внутри автомобиля. Вы делаете это отдельно. Иногда на другом заводе. Двигатель устанавливается в машине на конвейере.

Это дает вам больше гибкости как на заводе, так и в коде.

В дальнейшем я предлагаю реализовать шаблон для строителей - если у вас в машине будет больше деталей.

P.s. игнорировать "статические" s - я просто добавил их, чтобы избежать предупреждений IDE.

public static void main(String[] args) {
    Car car = new Car(EngineFactory.createEngine(1, 2));
    Car fastCar = new FastCar(EngineFactory.createEngine(1, 2, 1d, 2d), 1d, 2d);
}

static class EngineFactory{
    public static Engine createEngine(int x, int y){
        return new Engine(x, y);
    }

    public static Engine createEngine(int x, int y, double a, double b){
        return new FastEngine(x, y, a, b);
    }
}

public static class Car {
    private final Engine engine;
    public Car(Engine engine) {
        this.engine = engine;
    }
}

public static class FastCar extends Car {

    private final double a;
    private final double b;

    public FastCar(Engine engine, double a, double b) {
        super(engine);
        this.a = a;
        this.b = b;
    }
}

public static class FastEngine extends Engine {
    public FastEngine(int x, int y, double a, double b) {
        super(x, y);
    }
}

public static class Engine{
    int x;
    int y;

    public Engine(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

8
задан Barry Kelly 27 November 2008 в 20:55
поделиться

3 ответа

Я взял бы Yegge (и Ola Bini) мнения о статическом контроле типов с мелкой частицей соли. Если Вы будете ценить то, что статический контроль типов дает Вам, то Вы изучите, как система типов языка программирования Вы выбираете работы.

IIRC, ML использует '*' синтаксис для кортежей. <тип> * <тип> является типом "кортеж" с двумя элементами. Так, (1, 2) имел бы интервал * международный тип.

И Haskell и использование ML-> для функций. В ML интервал * интервал-> интервал был бы типом функции, которая берет кортеж интервала и интервала и отображает его на интервал.

Одна из причин, Вы могли бы видеть ошибку, которая неопределенно походит на тот Ola, заключенный в кавычки при прибытии в ML с другого языка, то, при попытке передать аргументы с помощью круглых скобок и запятых, как каждый был бы в C или Паскале к функции, которая берет два параметра.

Проблема, функциональные языки обычно образцовые функции больше чем одного параметра как функции, возвращая функции; все функции только берут отдельный аргумент. Если функция должна взять два аргумента, она вместо этого берет аргумент и возвращает функцию отдельного аргумента, который возвращает конечный результат и так далее. Подавать всю эту четкую, функциональную заявку сделано просто соединением (т.е. размещение выражений друг около друга).

Так, простая функция в ML (примечание: я использую F# в качестве своего ML), мог бы посмотреть немного как:

let f x y = x + y;;

Это имеет тип:

val f : int -> int -> int

(Функция, берущая целое число и возвращающая функцию, которая саму берет целое число и возвращает целое число.)

Однако, если Вы наивно называете его с кортежем:

f(1, 2)

... Вы получите ошибку, потому что Вы передали int*int чему-то, ожидая интервал.

Я ожидаю, что это - "проблема", в которой Ola пытался бросить клеветы. Я не думаю, что проблема так плоха, как он думает, хотя; конечно, это намного хуже в шаблонах C++.

8
ответ дан 5 December 2019 в 11:28
поделиться

Возможно, что это было в отношении плохо записанного компилятора, которому не удалось вставить круглые скобки для устранения неоднозначности сообщений об ошибках. А именно, функция ожидала кортеж int и возвратился int, но Вы передали кортеж int и функция от int кому: int. Более конкретно (в ML):

fun f g = g (1, 2);

f (42, fn x => x * 2)

Это произведет ошибку типа, подобную следующему:

Ожидаемый тип int * int -> int, получил тип int * (int -> int)

Если круглые скобки опущены, эта ошибка может быть раздражающе неоднозначной.

Стоит отметить, что эта проблема далека от того, чтобы быть характерным для Хиндли-Milner. На самом деле я не могу думать ни о каких странных ошибках типа, которые характерны для H-M. По крайней мере, ни один как данный пример. Я подозреваю, что Ola просто уносил дым.

4
ответ дан 5 December 2019 в 11:28
поделиться

Поскольку многие функциональные языки позволяют повторно связывать имена типов так же, как и переменные, на самом деле довольно легко получить подобную ошибку, особенно если вы используете несколько общие имена для своих типов (например, t ) в разных модулях. Вот простой пример в OCaml:

# let f x = x + 1;;
val f : int -> int = <fun>
# type int = Foo of string;;
type int = Foo of string
# f (Foo "hello");;
This expression has type int but is here used with type int

Здесь я заново привязал идентификатор типа int к новому типу, который несовместим со встроенным типом int . Приложив немного больше усилий, мы можем получить более или менее ту же ошибку, что и выше:

# let f g x y = g(x,y) + x + y;;
val f : (int * int -> int) -> int -> int -> int = <fun>
# type int = Foo of int;;
type int = Foo of int
# let h (Foo a, Foo b) = (Foo a);;
val h : int * int -> int = <fun>
# f h;;
This expression has type int * int -> int but is here used with type
  int * int -> int
3
ответ дан 5 December 2019 в 11:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: