No, los sistemas de tipo dinámico no son esencialmente más abiertos

Las guerras santas en Internet sobre los sistemas de tipos continúan sufriendo el mito generalizado de que los sistemas de tipos dinámicos son inherentemente más adecuados para modelar áreas temáticas del "mundo abierto". Por lo general, el argumento es: el propósito de la escritura estática es capturar todas las entidades con la mayor precisión posible, pero en el mundo real esto es simplemente inconveniente. Los sistemas reales deben estar acoplados de manera flexible y lo menos posible ligados a la presentación de datos, por lo que la tipificación dinámica conduce a un sistema más estable en su conjunto.



Esta historia suena convincente, pero no es verdad. El error en dicho razonamiento es que los tipos estáticos no están destinados a "clasificar el mundo" o determinar la estructura de cada valor en el sistema. La realidad es que los sistemas de tipo estático le permiten especificar exactamente cuánto debe saber un componente sobre la estructura de sus datos de entrada y, por el contrario, cuánto no sabe. En la práctica, los sistemas de tipo estático procesan perfectamente los datos con una estructura parcialmente conocida, así como también pueden asegurarse de que la lógica de la aplicación no asuma accidentalmente demasiado sobre los datos.


Dos mentiras sobre tipos


, . , , /r/programming:


[…], . , , «» , , - .
, , . JSON , . , . […] « » , .

, , , , . , - , , ? , , .


Hacker News :


, , pickle.load()?

, , , . , , .


, , . , , : . , ; , .


,


: , , , , ! , . , .


. , , . (payload), . , - , JSON EDN.


, , :


{
  "event_type": "signup",
  "timestamp": "2020-01-19T05:37:09Z",
  "data": {
    "user": {
      "id": 42,
      "name": "Alyssa",
      "email": "alyssa@example.com"
    }
  }
}

signup- . , . JavaScript, :


const handleEvent = ({ event_type, data }) => {
  switch (event_type) {
    case 'login':
      /* ... */
      break
    case 'signup':
      sendEmail(data.user.email, `Welcome to Blockchain Emporium, ${data.user.name}!`)
      break
  }
}

, Haskell? , Haskell, , , :


data Event = Login LoginPayload | Signup SignupPayload
data LoginPayload = LoginPayload { userId :: Int }
data SignupPayload = SignupPayload
  { userId :: Int
  , userName :: Text
  , userEmail :: Text
  }

instance FromJSON Event where
  parseJSON = withObject "Event" \obj -> do
    eventType <- obj .: "event_type"
    case eventType of
      "login" -> Login <$> (obj .: "data")
      "signup" -> Signup <$> (obj .: "signup")
      _ -> fail $ "unknown event_type: " <> eventType

instance FromJSON LoginPayload where { ... }
instance FromJSON SignupPayload where { ... }

handleEvent :: JSON.Value -> IO ()
handleEvent payload = case fromJSON payload of
  Success (Login LoginPayload { userId }) -> {- ... -}
  Success (Signup SignupPayload { userName, userEmail }) ->
    sendEmail userEmail $ "Welcome to Blockchain Emporium, " <> userName <> "!"
  Error message -> fail $ "could not parse event: " <> message

, (, , ). . , Reddit, , Haskell , ! Event, . , ? .


, JavaScript . , switch . , JavaScript . , .


, , . Event, , handleEvent. JavaScript, , :


const handleEvent = ({ event_type, data }) => {
  switch (event_type) {
    /* ... */
    default:
      throw new Error(`unknown event_type: ${event_type}`)
  }
}

, . , , . , , Haskell:


handleEvent :: JSON.Value -> IO ()
handleEvent payload = case fromJSON payload of
  {- ... -}
  Error _ -> pure ()

- «, », , . , ( ) . , ! , .


: Event Haskell « », , . , , . , , , .


, , , :


  • Haskell, . , , timestamp, . , , , , , !


  • , , Haskell userId SignupPayload, . , (, , userId ), ; , , , .


  • , , (shotgun parsing), , .



, , , , , . , , . , , , , , , .


JavaScript , Haskell: , JSON event_type «» signup data.user.name data.user.email. ! , JavaScript , . , ; , , - .



, , , , .


, , , - -. , , . , . JavaScript :


const handleEvent = (payload) => {
  const signedPayload = { ...payload, signature: signature(payload) }
  retransmitEvent(signedPayload)
}

( signature JSON), , . , ?


, : , . Haskell:


handleEvent :: JSON.Value -> IO ()
handleEvent (Object payload) = do
  let signedPayload = Map.insert "signature" (signature payload) payload
  retransmitEvent signedPayload
handleEvent payload = fail $ "event payload was not an object " <> show payload

, , JSON.Value. Event — JSON , , .


: , JSON- ( -), - JSON, - . , , , , . .


, , Haskell, JavaScript! JavaScript handleEvent ( JSON ), , , , spread- :


> { ..."payload", signature: "sig" }
{0: "p", 1: "a", 2: "y", 3: "l", 4: "o", 5: "a", 6: "d", signature: "sig"}

, . , . «» JSON Object, . -, , .




, . , API, , , UUID. «, » , API Haskell UUID:


type UserId = UUID

, Reddit, , ! API , UUID, , . UUID , , , ! , ?


, — . , — . , UserId — :


newtype UserId = UserId Text
  deriving (Eq, FromJSON, ToJSON)

, UUID, UserId, , Text. ( , ), UserIdFromJSON. , , UserIdUserId ToJSON. : .


, , . UserId , UserId .


1

, FromJSON UserId, , , fromJSON . , - . , , … UserId. , , ( , , , ).


— , . , , , .


-


, , , , , . pickle.load() Python? , , Python. pickle.dump(), pickle.load().


, , pickle.load(), — , pickle.dump(). , , . , , , .


, JSON, , pickle Python Python , . ? , , pickle.load(). , :


def load_value(f):
  val = pickle.load(f)
  #  -  `val`

, val , , , , , - . - - , , pickle.load(f) , , val!


, , , val val.foo() , . Java, val — , :


interface Foo extends Serializable {
  String foo();
}

, pickle.load() Java:


static <T extends Serializable> Optional<T> load(InputStream in, Class<? extends T> cls);

, , pickle.load(), Class<T> . Serializable.class , . : , -, - , ! , , JSON-.




Haskell? — serialise, API, , Java, . API , Haskell JSON, aeson, , , JSON Haskell — - - , -.


, , pickle.load(), . , . - , , , , . , (, REPL ), , .


. , , , , - , «» , , . , , , , , .


. , , , ( ). , , «» .


: ,


: . , , , , , .


, , . -, - (nominal typing). , , , , . , . , .


, , , , . , , -, , ( ).


. JavaScript Clojure - , - , . ( ) .


, , - , , . ( ) , (nominal typing). , ; (boilerplate).


, , . , , , . , :


  1. , , , , . ( ), : , .


  2. , , - . , , , . , .



Python, , , , TypeScript, , . , . - Clojure — , - — , - Clojure, - .


, : TypeScript, Flow, PureScript, Elm, OCaml Reason, . — Haskell, ; Haskell ( , ) .


2

, Haskell .


, Haskell , ? , ; Haskell, , . Haskell, , . , Haskell, , , . ( , , Haskell!)


: , , , . , , , . — , , , , . .

Source: https://habr.com/ru/post/undefined/


All Articles