все вышесказанное верно. Пожалуйста, будьте уверены, прежде чем это число в строке, сделав «typeot x === 'number», «другой мудрый он вернет NaN
var num = "fsdfsdf242342";
typeof num => 'string';
var num1 = "12423";
typeof num1 => 'number';
+num1 = > 12423`
Haskell допускает переменные более высокого типа. Диалекты ML, в том числе и Caml, допускают только переменные типа "*". Переведено на простой английский язык,
В Haskell переменная типа g
может соответствовать "конструктору типов" типа Может быть
или IO
или спискам. Таким образом, g x
в вашем примере с Хаскеллом будет нормально (жаргон: "доброжелательно"), если, например, g
это может быть
и x
это Integer
.
В ML переменная типа 'g
может соответствовать только "типу земли", как int
или string
, но никогда не может соответствовать конструктору типа, как опция
или list
. Поэтому никогда не правильно пытаться применить переменную типа к другому типу.
Насколько мне известно, в ML нет глубоких оснований для этого ограничения. Наиболее вероятным объяснением является исторический случай. Когда Милнер изначально придумал свои идеи о полиморфизме, он работал с очень простыми переменными типа, стоящими только для монотипов вида *. Ранние версии Хаскелла делали то же самое, а затем в какой-то момент Марк Джонс обнаружил, что делать выводы о типах переменных на самом деле довольно просто. Haskell был быстро переработан, чтобы позволить переменные более высокого типа, но ML никогда не догонял.
Люди в INRIA внесли много других изменений в ML, и я немного удивлен, что они никогда не делали этого. Когда я программирую на ML, мне, возможно, нравится иметь переменные более высокого типа. Но их нет, и я не знаю, как кодировать те примеры, о которых вы говорите, кроме как с помощью functors .
Вы можете сделать это, но вам нужно сделать немного хитрости:
newtype Fix f = In{out:: f (Fix f)}
Вы можете определить Cata впоследствии:
Cata :: (Functor f) => (f a -> a) -> Fix f -> a
Cata f = f.(fmap (cata f)).out
Это определит общий катаморфизм для всех функторы, которые вы можете использовать для создания своих собственных вещей. Пример:
data ListFix a b = Nil | Cons a b
data List a = Fix (ListFix a)
instance functor (ListFix a) where
fmap f Nil = Nil
fmap f (Cons a lst) = Cons a (f lst)
Вы можете сделать что-то подобное в OCaml, используя модули вместо типов и функторы (модули высшего порядка) вместо типов высшего порядка. Но это выглядит намного уродливее и не имеет возможности определения типа, поэтому вам придется вручную указывать много вещей.
module type Type = sig
type t
end
module Char = struct
type t = char
end
module List (X:Type) = struct
type t = X.t list
end
module Maybe (X:Type) = struct
type t = X.t option
end
(* In the following, I decided to omit the redundant
single constructors "Id of ...", "Compose of ...", since
they don't help in OCaml since we can't use inference *)
module Id (X:Type) = X
module Compose
(F:functor(Z:Type)->Type)
(G:functor(Y:Type)->Type)
(X:Type) = F(G(X))
let l : Compose(List)(Maybe)(Char).t = [Some 'a']
module Example2 (F:functor(Y:Type)->Type) (X:Type) = struct
(* unlike types, "free" module variables are not allowed,
so we have to put it inside another functor in order
to scope F and X *)
let iso (a:Compose(Id)(F)(X).t) : F(X).t = a
end