Компактность всех коллекций в текущей базе данных
db.getCollectionNames().forEach(function (collectionName) {
print('Compacting: ' + collectionName);
db.runCommand({ compact: collectionName });
});
И newtype
, и одинарный конструктор data
вводят один конструктор значения, но конструктор значения, представленный newtype
, является строгим, а конструктор значения, представленным данные
ленивы. Итак, если у вас есть
data D = D Int
newtype N = N Int
, то N undefined
эквивалентно undefined
и вызывает ошибку при вычислении.Но D undefined
не эквивалентен undefined
, и его можно оценить, пока вы не пытаетесь заглянуть внутрь.
Компилятор не мог справиться с этим сам.
Нет, не совсем - это тот случай, когда вы, как программист, можете решить, будет ли конструктор строгим или ленивым. Чтобы понять, когда и как сделать конструкторы строгими или ленивыми, вы должны гораздо лучше разбираться в ленивых вычислениях, чем я. Я придерживаюсь идеи в Отчете, а именно, что newtype
существует для того, чтобы вы могли переименовать существующий тип, например, имея несколько разных несовместимых видов измерений:
newtype Feet = Feet Double
newtype Cm = Cm Double
оба ведут себя точно так же, как Double
] во время выполнения, но компилятор обещает, что вы их не запутаете.
Сверху у меня в голове; объявления данных используют ленивую оценку при доступе и хранении своих «членов», тогда как newtype этого не делает. Newtype также удаляет все предыдущие экземпляры типов из своих компонентов, эффективно скрывая его реализацию; тогда как данные оставляют реализацию открытой.
Я обычно использую newtype, когда избегаю шаблонного кода в сложных типах данных, где мне не обязательно нужен доступ к внутренним компонентам при их использовании. Это ускоряет компиляцию и выполнение, а также снижает сложность кода, в котором используется новый тип.
Когда я впервые прочитал об этом, я нашел эту главу Мягкого введения в Haskell довольно интуитивно понятной.