Não, os sistemas dinâmicos não são mais abertos

As guerras santas na Internet sobre sistemas de tipos continuam sofrendo com o mito generalizado de que sistemas de tipos dinâmicos são inerentemente mais adequados para modelar áreas de assunto do “mundo aberto”. Normalmente, o argumento é: o objetivo da tipagem estática é capturar todas as entidades com a maior precisão possível, mas no mundo real isso é simplesmente inconveniente. Os sistemas reais devem ser fracamente acoplados e o mínimo possível vinculados à apresentação dos dados; portanto, a digitação dinâmica leva a um sistema mais estável como um todo.



Essa história parece convincente, mas não é verdadeira. O erro desse raciocínio é que os tipos estáticos não se destinam a "classificar o mundo" ou determinar a estrutura de cada valor no sistema. A realidade é que os sistemas do tipo estático permitem especificar exatamente quanto um componente deve saber sobre a estrutura de seus dados de entrada e, inversamente, quanto ele não sabe. Na prática, os sistemas do tipo estático processam perfeitamente os dados com uma estrutura parcialmente conhecida, além de garantir que a lógica do aplicativo não assuma acidentalmente muito sobre os dados.


Duas 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