Verwenden Sie beispielsweise ein "starkes" System in der realen Welt für umfangreiche Web-Apps?

29

Ich weiß, dass dies eine sehr breite, mehrdeutige und möglicherweise philosophische Frage ist. Bis zu einem gewissen Grad ist das wichtigste Schlüsselwort in der Frage - das "starke" Typensystem - selbst - schlecht definiert . Lassen Sie mich erklären, was ich meine.

Gesamtzusammenhang für die Frage

Wir haben eine sehr umfangreiche Web-App in Ruby on Rails erstellt und waren im Allgemeinen sehr zufrieden mit unserem Stack. Wenn wir wollen, können wir wirklich schnell etwas versenden - etwas, das für 90% des "Business" -Falls funktioniert, ohne dass wir uns über 10% Edge-Fälle Gedanken machen müssen. Auf der anderen Seite können wir mit Hilfe von Code-Reviews und Test-Coverage langsam und überlegt vorgehen und sicherstellen, dass wir alle Grundlagen abdecken - wiederum nur in Situationen, die eine genauere Prüfung und Sicherheit verdienen.

Mit dem Anwachsen des Teams wurde es mir jedoch unangenehm, dass kein "Sicherheitsnetz" direkt in unseren Stapel gebacken wurde.

Wir haben vor kurzem damit begonnen, native Android-Entwicklung auf Java durchzuführen. Und ich wurde (angenehm) an die Sicherheit erinnert, die eine kompilierte / statische / stark typisierte Sprache bietet.

  • Falsch geschriebene Variablen, falsche Datentypen, falsche Funktionsaufrufe und eine Vielzahl trivialer Fehler werden von Ihrer IDE selbst abgefangen. Alles, weil die IDE sich in den Compiler einbinden und bestimmte Aspekte der Programmkorrektheit überprüfen kann.
  • Müssen Sie eine Funktionssignatur ändern? Einfach. Die Compiler + IDE kann Ihnen helfen, ALLE Aufrufstellen zu erkennen.
  • Müssen Sie sicherstellen, dass bestimmte Ausnahmen immer behandelt werden? Überprüfte Ausnahmen zu Ihrer Rettung.

Diese Sicherheitsmerkmale haben zwar ihre Vorteile, aber ich bin mir auch ihrer Nachteile bewusst. Mehr noch, in der Welt von "Boilerplate Heavy" Java. Aus diesem Grund habe ich mich anstelle von Java mit den modernen, stark typisierten Sprachen befasst, an denen die Menschen in diesen Tagen zu arbeiten begonnen haben. Zum Beispiel: Scala, Rust, Haskell usw. Was mich am meisten interessiert, ist die Leistungsfähigkeit ihrer Typsysteme und die Überprüfung der Statik / Kompilierzeit.

Nun die Frage

Wie verwende ich diese leistungsstarken Typsysteme und Funktionen zur statischen / Kompilierungszeit in größeren Anwendungen?

Wie würde ich mich zum Beispiel jenseits der üblichen "Hallo Welt" -Einführungen in diese leistungsstarken Funktionen bewegen? Ein System, das ein Rich-Type-System zur Modellierung eines Business-Domain-Problems verwendet? Hilft oder behindert das Typsystem, wenn Sie sich in der Zone mit 30.000 LOC + befinden? Was passiert mit dem von diesen Typsystemen bereitgestellten Sicherheitsnetz (und Überprüfungen der Kompilierungszeit), wenn Ihr System mit der schwach typisierten Außenwelt interagiert, z. über JSON- oder XML-APIs, verschiedene Datenspeicher, Benutzereingaben usw.

Saurabh Nanda
quelle
12
Dies ist kein Thema, da es keine echte Antwort gibt. Die Frage soll zu einer Diskussion mit der Meinung anregen ("Ich mag / mag keine statischen Typen, weil ..."), keine sachliche Erklärung . Mein Rat wäre, einen der spezifischeren Teile Ihrer Frage auszuwählen, z. B. "Was passiert mit dem von diesen Typsystemen bereitgestellten Sicherheitsnetz, wenn Ihr System mit der schwach typisierten Außenwelt interagiert?" und schreiben Sie die Frage um, um darüber zu sein. Sie erhalten endgültige Antworten, die für zukünftige Leser auf diese Weise nützlich sein werden.
Benjamin Hodgson
5
Ressourcenempfehlungen sind auch hier nicht thematisch relevant (weil solche Antworten schnell veraltet sind und wir wirklich nicht besser als Google darin sind). Wie Benjamin sagte, sind einige beantwortbare Fragen in Ihrem Beitrag vergraben, aber der gesamte Beitrag in seinem aktuellen Zustand verlangt im Wesentlichen, dass die Leute ihre Erfahrungen mit diesen Sprachen beschreiben. Dies passt besser zu Quora oder Reddit als zu StackExchange Seite? ˅. Ich stimme nicht herab, weil diese Frage gut gestellt ist, aber es ist einfach keine StackExchange-Frage.
Ixrec
4
Ein Typensystem ist ein Werkzeug, und wie jedes andere Werkzeug hängt seine Wirksamkeit in hohem Maße nicht vom Werkzeug selbst, sondern vom Anwender ab. Sie können das Typsystem einer Sprache wie Haskell nutzen, um Invarianten über Ihre Geschäftslogik auf Typebene zu codieren und diese Invarianten zur Compilerzeit von einem Computer (dem Compiler) überprüfen zu lassen. Dazu müssen Sie jedoch die Semantik von verstehen das Typensystem und die Typprüfung. Die richtige Frage ist nicht "Ist dies ein gutes Tool für Web-Inhalte?"
user2407038
5
Die meisten Dinge, die Sie beschreiben, haben nichts mit dem Typensystem zu tun. Sie sind reine IDE-Funktionen. Mit Ausnahme von aktivierten Ausnahmen (kein Wortspiel beabsichtigt) waren alle von Ihnen erwähnten Funktionen in Smalltalk-IDEs enthalten, lange bevor sie in IDEs für statisch typisierte Sprachen erschienen. Tatsächlich begann eine der am häufigsten verwendeten Java-IDEs mit einer modifizierten Smalltalk-IDE (IBM VisualAge Smalltalk), die zum Verständnis von Java-Code modifiziert wurde, jedoch noch in Smalltalk geschrieben und als VisualAge Java veröffentlicht und dann nach Java portiert wurde und veröffentlicht als…
Jörg W Mittag
4
… VisualAge Java Micro Edition, die dann in wiederverwendbare Komponenten zerlegt und als Open Source unter dem Namen Eclipse veröffentlicht wurde). Etwas ironisch im Zusammenhang mit dieser Frage ist es gerade wegen der Dynamik von Smalltalk-Systemen, dass Smalltalk-IDEs so leistungsfähig sind. Beispielsweise wurden automatisierte Refactorings erfunden und erstmals in Smalltalk implementiert. Nach Ihrer Logik muss Haskell die besten IDEs haben, da es das stärkste und strengste statische Typsystem aller von Ihnen genannten Sprachen hat. Aber das tut es nicht. Sie haben auch "Hooking in the Compiler" erwähnt. Dies hat…
Jörg W Mittag

Antworten:

34

Ich werde aus Zeitgründen eine kurze Antwort geben, arbeite aber derzeit an zwei großen Projekten (> 100.000 LOC in Haskell) - flowbox.io und luna-lang.org. Wir verwenden Haskell für alle Teile, einschließlich des Backends, des Compilers unserer Programmiersprache und sogar der webGL-basierten GUI. Ich muss zugeben, dass das starke Typensystem und die "abhängige Art" -ähnliche Maschinerie Sie führen und Sie vor Belastungen und Schwierigkeiten bewahren können, die aus anderen Sprachen bekannt sind. Wir verwenden die Typen sehr ausgiebig und alles, was in der Kompilierzeit überprüft werden konnte, wird so gemacht. Tatsächlich haben wir in den letzten 3 Jahren der Entwicklung nie einen Laufzeitfehler oder einen Stapelüberlauf festgestellt (und das ist wirklich unglaublich). Die einzigen Fehler sind offensichtliche Logikfehler, die von Programmierern gemacht werden. Viele Leute sagen, dass, wenn etwas in Haskell kompiliert wird, es einfach funktioniert und Sie ziemlich sicher sein sollten, dass es eines Tages nicht in Ihr Gesicht bläst.

Beantwortung des ersten Teils der Frage: Sie können sich mit diesen leistungsstarken Typsystemfunktionen vertraut machen, indem Sie einige großartige Blogs lesen, z.

Tatsächlich gibt es viele andere nette Blogs da draußen (wie Planet Haskell ). Wie auch immer, die beste Methode, um die fortschrittlichen Typsysteme wirklich zu verstehen, ist die Entwicklung einer nützlichen Open-Source-Bibliothek. Wir (bei Flowbox & New Byte Order) veröffentlichen viele Bibliotheken (Sie finden sie bei Hackage). Wenn Sie also keine Ahnung haben, was Sie entwickeln sollen, können Sie sich jederzeit an unseren Projekten beteiligen - schicken Sie mir einfach eine E-Mail, wann immer Sie möchten wollen (Mail verfügbar bei luna-lang.org ).

danilo2
quelle
4
"Viele Leute sagen, wenn etwas in Haskell kompiliert wird, funktioniert es einfach und Sie sollten ziemlich sicher sein, dass es eines Tages nicht ins Gesicht sprengt.": Ich habe Haskell nur für kleine (wenn auch nicht triviale) Projekte verwendet , aber ich kann das bestätigen: Sobald der Haskell-Compiler zufrieden ist, finde ich selten noch Fehler.
Giorgio
1
Ich bin wahrscheinlich einer der "Haskell" -Typen, die Typen am meisten hassen (so sehr habe ich schließlich meine eigene Version von Haskell ohne Typen geschrieben ) - aber aus verschiedenen Gründen tun es die meisten Menschen. Wenn es um Software-Engineering geht, habe auch ich das Gefühl, dass Ihr Programm einfach funktioniert, wenn GHC zufrieden ist. Haskell-ähnliche Systeme sind das ultimative Werkzeug, um nicht nur menschliche Programmierfehler zu erkennen, sondern auch große Codebasen unter Ihrer Kontrolle zu halten. (Ich erinnere mich immer an Giovannis Rechtfertigung für Mewtus Rüstungen, wenn ich Tippfehler beheben muss.)
MaiaVictor
Gabriel Gonzales 'Blog ist der beste Anfang.
Sam Boosalis
@ danilo2 Haben eine E-Mail an die Kontaktadresse auf Ihrer Unternehmenswebsite gesendet. Bitte Sie, zu antworten. Vielen Dank!
Saurabh Nanda
@ SaurabhNanda: Ich habe unseren Posteingang zweimal überprüft und sehe keine Nachricht von Ihnen. Haben Sie es an <at> luna-lang.org gesendet? Bitte kontaktieren Sie mich direkt unter <dot> danilo <at> gmail <dot> com und wir werden untersuchen, was die Ursache für dieses Problem war :)
danilo2
17

Nun, schwaches vs. starkes Tippen ist ziemlich vage definiert. Da der allgemeine Gebrauch von "starker Typisierung" am ehesten darin besteht, Dinge zu bezeichnen, die das Gießen von Typen erschweren, bleibt nichts anderes übrig, um noch stärkere Typensysteme zu beschreiben. Es ist wie zu sagen, wenn Sie weniger als 30 Pfund tragen können, sind Sie schwach, und jeder, der mehr heben kann, ist in der gleichen Kategorie von "stark" - eine irreführende Unterscheidung.

Also bevorzuge ich die Definition:

  • Schwach getypte Systeme verwenden Typen, um Sie daran zu hindern, bestimmte Dinge (wie Fehler) zu tun.
  • Stark typisierte Systeme verwenden Typen, um Dinge für Sie zu erledigen

Was meine ich damit, Dinge für dich zu tun? Nun, lassen Sie uns das Schreiben einer Bildkonvertierungs-API im Servant-Framework untersuchen (in Haskell, aber Sie müssen es nicht wirklich wissen, um mitzumachen, Sie werden sehen ...)

{-# LANGUAGE
    TypeOperators,
    DataKinds
    #-}

import Codec.Picture
import Data.Proxy
import Network.Wai.Handler.Warp (run)
import Servant
import Servant.JuicyPixels

main :: IO ()
main = run 8001 conversion

Dies bedeutet, dass wir einige Module, einschließlich des Servant-Pakets und des JuicyPixels-Plugins für Servant, benötigen und dass der Haupteinstiegspunkt des Programms darin besteht, die Konvertierungsfunktion auf Port 8001 als Server über das Warp-Backend auszuführen. Ignoriere das Sprachbit.

conversion :: Application
conversion = serve (Proxy :: Proxy ConversionApi) handler

Dies bedeutet, dass die Konvertierungsfunktion ein Server ist, auf dem die API dem Typ 'ConversionApi' entsprechen muss und die Anforderungen von der Funktion verarbeitet werden handler

type ConversionApi
     = ReqBody '[BMP, GIF, JPEG 50, PNG, TIFF, RADIANCE] DynamicImage
    :> Post '[BMP, GIF, JPEG 50, PNG, TIFF, RADIANCE] DynamicImage

Dies gibt den ConvesionApiTyp an. Es heißt, wir sollten eingehende Inhaltstypen akzeptieren, die in der Liste '[BMP, GIF, JPEG 50, PNG, TIFF, RADIANCE] angegeben sind, und sie als DynamicImage behandeln und ein DynamicImage zurückgeben, das in denselben Inhaltsbereich konvertiert wurde Typen. Machen Sie sich keine Gedanken darüber, was:> bedeutet, stellen Sie es sich vorerst als glückliche Magie vor.

Aufgrund meiner bevorzugten Definition kann ein schwach typisiertes System nun Folgendes sicherstellen:

  • Sie geben nicht den falschen ausgehenden Inhaltstyp zurück
  • Sie analysieren die eingehende Anforderung nicht als den falschen Inhaltstyp
  • Wenn unser Server komplizierter wäre, könnten wir keine ungültigen URIs erstellen, aber wir geben keine HTML-Seiten zurück, die Links enthalten (und der Typ stellt sicher, dass dies nicht möglich ist!).
  • Ein wirklich ehrgeiziges schwaches Typisierungssystem könnte sogar prüfen, ob wir alle eingehenden und ausgehenden Inhaltstypen vollständig verarbeiten, sodass der Typ auch als Spezifikationsdokument und nicht nur als Einschränkung fungieren kann.

Alle hohen Ziele, aber nicht genug, um sich als stark typisiertes System zu qualifizieren, wenn man die obige Definition zugrunde legt. Und jetzt müssen wir uns dem schwierigen Teil des eigentlichen Schreibens von Code zuwenden, der dieser Spezifikation folgt. In einem wirklich starken Typensystem schreiben wir:

handler = return

Und dann sind wir fertig. Das war's, es gibt keinen Code mehr zum Schreiben . Dies ist ein voll funktionsfähiger Webserver (Modulo alle Tippfehler, die ich verpasst habe). Der Typ hat dem Compiler alles mitgeteilt, was er zum Erstellen unseres Webservers aus den von uns definierten und importierten Typen und Paketen (Module technisch gesehen) benötigt.

Wie lernen Sie dies auf der Hauptanwendungsskala? Nun, es unterscheidet sich nicht wesentlich von der Verwendung in kleineren Anwendungen. Absolute Typen interessieren sich nicht dafür, wie viel Code in Bezug auf sie geschrieben ist.

Die Typprüfung zur Laufzeit ist etwas, das Sie wahrscheinlich vermeiden möchten, da dies einen großen Teil des Nutzens einspart und es den Typen ermöglicht, die Arbeit mit Ihrem Projekt komplizierter zu gestalten, anstatt die Dinge durch Typen zu vereinfachen.

Daher ist es meist nur eine Frage der Übung, Dinge mit Typen zu modellieren. Die beiden Hauptmethoden zum Modellieren von Dingen (oder zum Erstellen von Dingen im Allgemeinen) sind Bottom-up und Top-down. Top-down beginnt mit der höchsten Ebene von Operationen, und wenn Sie das Modell erstellen, haben Sie Teile, bei denen Sie die Modellierung auf einen späteren Zeitpunkt verschieben. Bottom-up-Modellierung bedeutet, dass Sie mit Basisoperationen beginnen, genau wie Sie mit Basisfunktionen beginnen, und dann immer größere Modelle erstellen, bis Sie die Operation des Projekts vollständig erfasst haben. Bottom-up ist konkreter und lässt sich wahrscheinlich schneller erstellen, aber Top-down kann Ihre Modelle auf niedrigerer Ebene besser darüber informieren, wie sie sich tatsächlich verhalten müssen.

Typen beziehen sich im wahrsten Sinne des Wortes auf Mathematik. Es gibt also keine Obergrenze dafür, wie kompliziert sie werden können, oder einen Punkt, an dem man "fertig" sein kann, um etwas über sie zu lernen. Nahezu alle Ressourcen außerhalb von Universitätskursen auf höherer Ebene beziehen sich auf die Funktionsweise von Typen in einer bestimmten Sprache. Sie müssen sich also auch dafür entscheiden.

So gut ich kann, können Typen wie folgt geschichtet werden:

  • Sehr schwach getippt, Dinge wie JavaScript, in denen [] + {} definiert ist
  • Schwach getippt wie Python, wo Sie nicht [] + {} tun können, aber das wird nicht überprüft, bis Sie es versuchen
  • Schwach wie C oder Java getippt, wo Sie [] + {} nicht tun können, dies jedoch beim Kompilieren überprüft wird, verfügen Sie jedoch nicht über die erweiterten Typfunktionen
  • Spreizung der Grenze zwischen schwach und stark typisiert, z. B. Metaprogrammierung von C ++ - Vorlagen und einfacherem Haskell-Code, bei dem Typen nur Eigenschaften erzwingen.
  • Wie bei komplizierteren Haskell-Programmen, bei denen Typen Dinge tun, wie oben gezeigt
  • Die sehr stark typisierten, wie Agda oder Idris, bei denen Typen und Werte interagieren und sich gegenseitig einschränken können. Dies ist so stark wie Typsysteme, und das Programmieren darin ist dasselbe, als würden Sie mathematische Beweise darüber schreiben, was Ihr Programm tut. Hinweis: Bei der Codierung in Agda werden mathematische Beweise nicht buchstäblich geschrieben, Typen sind mathematische Theorien, und Funktionen mit diesen Typen sind konstruktive Beispiele, die diese Theorien beweisen.

Je weiter unten auf dieser Liste Sie sich befinden, desto mehr können Typen für Sie tun, aber ganz unten steigen Sie in die Stratosphäre auf und die Luft wird etwas dünn - das Paket-Ökosystem ist viel kleiner und Sie ' Ich muss mehr Dinge selbst schreiben, als eine relevante Bibliothek gefunden zu haben. Die Eintrittsbarriere steigt auch mit dem Abstieg, da Sie das Typensystem so gut verstehen müssen, dass Sie umfangreiche Programme schreiben können.

Steven Armstrong
quelle
Beachten Sie, dass Sie der Liste auf Typebene kein Apostroph voranstellen müssen, wenn die Liste mehr als ein Element enthält. Das Apostroph ist nur für Listen mit 0 oder 1 Elementen auf Typebene erforderlich, da sie nicht eindeutig sind (sie könnten sich auf den normalen Listentypkonstruktor beziehen)
Gabriel Gonzalez,
1
Ich bin mir bewusst, aber ich hatte den Eindruck, dass das Apostroph nur eine gute Form für heraufgestufte Datentypen im Allgemeinen ist. ZB das Proxy :: Proxy Truefunktioniert, aber es ist besser, es so zu schreiben Proxy :: Proxy 'True.
Steven Armstrong
1
Es scheint besser, die verschiedenen Achsen, nach denen Typsysteme klassifiziert werden können, nicht zu kollabieren. Der Lambda-Würfel von Barendregt enthält bereits drei, und zusätzlich schließen Sie entlang der einzelnen schwach-starken Achse statischen vs. dynamischen und parametrischen vs. Ad-hoc-Polymorphismus ein (letzterer ermöglicht es der Servant-Technik, Typen einen Großteil der Arbeit zu leisten) ').
user2141650
1
Richtig, aber die Antwort ist schon sehr lange, und Sie müssen auf dem besten Weg sein, die Typentheorie zu studieren, bevor der Lambda-Würfel wirklich Sinn ergibt. Ausserhalb von Nischensprachen (und da ich Haskell und sogar Agda bereits mit einbeziehe, meine ich wirklich ziemlich Nischensprachen) werden Sie keine Sprache finden, die beispielsweise abhängige Typen, aber keine Typoperatoren enthält .
Steven Armstrong
Können Sie die '[xs]Syntax kurz erläutern ? Dies ist eindeutig keine Char, aber ich verstehe weder, wie TypeOperatorsoder wie DataKindseine alternative Syntax aktiviert wird. Ist es eine Art Quasiquotierung?
wchargin
10

Ich habe gerade angefangen, im Kernteam einer großen Plattform zu arbeiten, die in Scala geschrieben wurde. Sie können sich erfolgreiche Open Source-Anwendungen wie Scalatra, Play oder Slick ansehen, um zu sehen, wie diese mit einigen Ihrer detaillierteren Fragen zur Interaktion mit dynamischen Datenformaten umgehen.

Einer der großen Vorteile der starken Typisierung von Scala liegt in der Benutzererziehung. Das Kernteam kann Entscheidungen treffen und diese Entscheidungen im Typensystem durchsetzen. Wenn also andere Teams, die mit den Entwurfsprinzipien viel weniger vertraut sind, mit dem System interagieren müssen, korrigiert der Compiler sie und das Kernteam korrigiert die Dinge nicht ständig in Anfragen ziehen. Dies ist ein großer Vorteil in einem großen System.

Natürlich können nicht alle Entwurfsprinzipien in einem Typsystem durchgesetzt werden. Je stärker Ihr Typsystem ist, desto mehr Entwurfsprinzipien können Sie im Compiler durchsetzen.

Wir können es den Nutzern auch leichter machen. Oft arbeiten sie nur mit regulären Sammlungen oder Fallklassen, und wir konvertieren sie nach Bedarf für den Netzwerktransport automatisch in JSON oder was auch immer.

Starke Typisierung hilft auch bei der Unterscheidung zwischen nicht bereinigten und bereinigten Eingaben, was die Sicherheit verbessern kann.

Starkes Tippen hilft auch, dass sich Ihre Tests mehr auf Ihr tatsächliches Verhalten konzentrieren , anstatt eine Reihe von Tests zu benötigen, die nur Ihre Typen testen. Es macht das Testen viel angenehmer, fokussierter und damit effektiver.

Der Hauptnachteil ist die Unkenntnis der Sprache und des Sprachparadigmas, und das kann mit der Zeit korrigiert werden. Ansonsten haben wir festgestellt, dass es sich gelohnt hat.

Karl Bielefeldt
quelle
8

Obwohl dies keine direkte Antwort ist (da ich noch nicht an +30.000 LOC-Code-Datenbanken in Haskell gearbeitet habe :( ..), bitte ich Sie, https://www.fpcomplete.com/business/resources/case-studies zu lesen / die eine Menge von Fallstudien von haskell in aktuellen Branchenumgebungen enthält.

Ein weiterer guter Artikel ist IMVU, der beschreibt, welche Erfahrungen sie mit der Umstellung auf haskell gemacht haben - http://engineering.imvu.com/2014/03/24/what-its-like-to-use-haskell/ .

Aus persönlicher Erfahrung in größeren Anwendungen hilft Ihnen das Typensystem sehr , insbesondere wenn Sie versuchen, so viel wie möglich in Typen zu codieren. Die wahre Kraft ist wirklich offensichtlich, wenn es darum geht, Dinge umzugestalten - was bedeutet, dass Wartung und dergleichen eine viel weniger beunruhigende Aufgabe werden.

Ich werde ein paar Links zu Ressourcen ausgeben, die ich empfehle, da Sie ziemlich viele Fragen gleichzeitig stellen:

Abschließend sei angemerkt, dass der Umgang mit der Außenwelt auf verschiedene Weise erfolgt. Es gibt Bibliotheken wie Aeson für JSON, Esqueleto für SQL und viele mehr , die sicherstellen, dass Ihre Dokumente typensicher sind.

Tehnix
quelle
1
danke für die antwort die fallstudien auf fpcomplete.com/business/resources/case-studies sind jedoch nicht mehr verfügbar.
Saurabh Nanda
Die Fallstudien wurden anscheinend
Steven Shaw,
3

Was ich gesehen habe:

Ich habe einige große Ruby-Webanwendungen (Rails), eine große Haskell-Webanwendung und mehrere kleinere gearbeitet. Mit dieser Erfahrung muss ich sagen, dass die Arbeit an den Haskell-Anwendungen in Bezug auf Wartung und geringere Lernkurve viel einfacher ist als bei Rails. Ich bin der Meinung, dass diese Vorteile sowohl auf das Typensystem von Haskell als auch auf den funktionalen Programmierstil zurückzuführen sind. Im Gegensatz zu vielen anderen bin ich jedoch der Meinung, dass der "statische" Teil des Typensystems nur insofern eine große Bequemlichkeit darstellt, als es noch Vorteile bei der Verwendung dynamischer Verträge gibt.

Was ich glaube

Es gibt ein nettes Paket mit dem Namen Contracts Ruby, das einige der Hauptfunktionen bereitstellt, die meiner Meinung nach dazu beitragen, dass Haskell-Projekte bessere Wartungseigenschaften erzielen. Verträge Ruby führt seine Überprüfungen zur Laufzeit durch, sodass es in Kombination mit hoher Testkonvergenz am besten ist. Es bietet jedoch immer noch die gleiche Inline-Dokumentation und Aussagekraft wie die Verwendung von Typanmerkungen in Sprachen wie Haskell.

Anwser zur Frage

Um die oben gestellten Fragen zu beantworten, gibt es viele Stellen, an denen man sich mit Haskell und anderen Sprachen mit fortschrittlichen Typsystemen vertraut machen kann. Um ganz ehrlich zu sein, diese Dokumentationsquellen sind zwar für sich genommen hervorragend, aber im Vergleich zu der Fülle an Dokumentationen und praktischen Ratschlägen, die in Ruby, Python, Java und anderen solchen Sprachen zu finden sind, scheinen sie alle ein wenig überwältigend. In jedem Fall wird Real World Haskell alt, ist aber immer noch eine gute Ressource.

Kategorietheorie

Wenn Sie sich für Haskell entscheiden, werden Sie auf große Mengen an Literatur stoßen, die sich mit Kategorietheorie befasst. IMHO Kategorietheorie ist nützlich, aber nicht notwendig. Angesichts der Verbreitung in der Haskell-Community ist es leicht, die Vor- und Nachteile von Typen mit Gefühlen über die Praktikabilität der Kategorietheorie zu verbinden. Es ist hilfreich, sich daran zu erinnern, dass es sich um zwei verschiedene Dinge handelt, das heißt, Implementierungen, die von der Kategorietheorie geleitet werden, können sowohl in dynamisch typisierten als auch in statischen Sprachen durchgeführt werden (modulo die Vorteile, die das Typensystem bietet). Fortgeschrittene Typensysteme sind im Allgemeinen nicht an die Kategorietheorie und die Kategorietheorie nicht an Typensysteme gebunden.

Mehr zu Typen

Wenn Sie mehr über das Programmieren mit Typen und die darin enthaltenen Techniken erfahren (was aufgrund des Spaßes recht schnell geschieht), möchten Sie mehr mit dem Typensystem ausdrücken. In diesem Fall schaue ich mir einige der folgenden Ressourcen an und mache die Werkzeuganbieter darauf aufmerksam, dass wir Werkzeuge in Industriequalität mit diesen Funktionen nur in einem Paket mit einer benutzerfreundlichen Oberfläche (wie Contracts Ruby) benötigen:

Eric
quelle
2

Erstens habe ich das Gefühl, dass in den Antworten eine Verwechslung zwischen schwach und stark getippt und statisch und dynamisch getippt besteht. Link das OP zur Verfügung gestellt macht deutlich die Unterscheidung:

Ein starkes Typensystem ist ein Typensystem mit einer für Sie attraktiven Einschränkung der Kompilierungszeit oder Laufzeitfunktion.

Ein schwaches Typensystem ist ein Typensystem, dem diese Einschränkung oder Funktion fehlt.

Beispielsweise sind C, C ++ und Java statisch typisiert, da Variablen zur Kompilierungszeit typisiert werden. C und C ++ können jedoch als schwach typisiert betrachtet werden, da die Sprache die Umgehung von Einschränkungen mithilfe von void *Zeigern und Umsetzungen ermöglicht. Mehr zu diesem Thema.

Bei dieser Unterscheidung kann eine starke Typisierung nur besser sein. Je früher das Scheitern, desto besser.

Ich glaube jedoch nicht, dass beim Schreiben großer Programme das Typensystem eine wichtige Rolle spielt. Der Linux-Kernel besteht aus zehn Millionen LOC, die in C und Assembly geschrieben wurden. Er gilt als sehr stabiles Programm und ist kilometerweit von meinen 200 Java-Zeilen entfernt, die wahrscheinlich voller Sicherheitslücken sind. Auch wenn dynamisch getippte "Skriptsprachen" beim Schreiben großer Programme einen schlechten Ruf haben, gibt es gelegentlich Beweise dafür, dass sie unverdient sind (wie Python Django, über 70.000 LOC).

Meiner Meinung nach dreht sich alles um den Qualitätsstandard. Die Verantwortung für die Skalierbarkeit großer Anwendungen sollte nur von den Programmierern und Architekten und deren Willen übernommen werden, die Anwendung sauber, getestet, gut dokumentiert usw. zu machen.

Arthur Havlicek
quelle
-1

Wo kann man nachlesen, wie diese leistungsstarken Typsysteme und Funktionen zur statischen / Kompilierungszeit in größeren Anwendungen verwendet werden?

Aus der vorherigen Antwort https://www.fpcomplete.com/business/resources/case-studies/

Wie kommt man über die üblichen "Hallo Welt" -Einführungen in diese leistungsstarken Funktionen hinaus?

Es ist wirklich wie jede andere Sprache, um Kraft aufzubauen

Wie kann man ein Rich-Type-System verwenden, um ein Business-Domain-Problem zu modellieren?

Mit abstrakten Datentypen oder allgemeiner mit Polymorphismus

Hilft oder behindert das Typsystem, wenn Sie sich in der Zone 30.000 LOC + befinden?

Es hilft den ganzen Weg. Das Typensystem hilft Ihnen beim Schreiben des Codes, da es Ihnen die Form des gewünschten Ergebnisses angibt. Eigentlich schreibt Agda Code für dich.

PS: Machen Sie nicht den Fehler, ein Typensystem zu haben und die Typen selbst schreiben zu müssen, was idiotisch ist: Computer können es für Sie tun.

Was passiert mit dem von diesen Typsystemen bereitgestellten Sicherheitsnetz (und Überprüfungen der Kompilierungszeit), wenn Ihr System mit der schwach typisierten Außenwelt interagiert, z. über JSON- oder XML-APIs, verschiedene Datenspeicher, Benutzereingaben usw.

Das ist großartig, denn wenn Sie die Struktur von Werten über Typen kennen, kann der Computer einen Weg finden, Serializer für Sie zu schreiben (de).

Wenn Sie wirklich etwas über Typen und Abstraktion wissen möchten, finden Sie die beste Einführung in das Verständnis von Typen, Datenabstraktion und Polymorphismus

Es ist ein Papier, keine Fallstudie mit schönen Bildern, aber es ist aufschlussreich

nicolas
quelle
-2

Als .NET-Programmierer, der viel an Webanwendungen arbeitet, sehe ich sowohl die getippte C # - als auch die untypisierte Javascript-Seite der Dinge.

Ich bin mir nicht sicher, ob ich Literatur zu den von Ihnen gestellten Fragen gesehen habe. Mit einer getippten Sprache nehmen Sie all diese Dinge als selbstverständlich an. Bei einem Typ ohne Typ sehen Sie, wie Sie die Typen als unnötigen Overhead definieren.

Persönlich kann man meiner Meinung nach nicht leugnen, dass eine stark typisierte Sprache die von Ihnen beschriebenen Vorteile zu sehr geringen Kosten bietet (im Vergleich zum Schreiben gleichwertiger Komponententests). Die Interaktion mit schwach typisierten Systemen umfasst normalerweise generische Typen wie Arrays oder Wörterbücher von Objekten wie DataReader oder die kreative Verwendung von Zeichenfolgen oder der neuen dynamischen Klasse. Im Wesentlichen funktioniert alles, Sie erhalten nur einen Laufzeitfehler anstelle der Kompilierungszeit.

Wenn Sie ein sehr kurzes Programm schreiben möchten, beispielsweise eine Funktion in ein paar Zeilen definieren, um mit einer größeren Anwendung zu arbeiten, haben Sie einfach keinen Platz, um Klassen zu deklarieren. Sicherlich ist dies die Nische, die untypisierte Sprachen wie JS besetzen?

Ewan
quelle
Meinen Sie getippt / untypisiert oder statisch getippt / dynamisch getippt? JavaScript ist nicht untypisiert, sondern dynamisch typisiert.
Giorgio
2
Sie müssen die Typen nicht definieren. Jede anständige Sprache wird die Typen für Sie ableiten: haskell, ocaml, sml, F # ...
Nicolas
1
Wenn Sie an eine stark typisierte Sprache gewöhnt sind, ist alles andere untypisiert. Wenn ich sage, definieren Sie die Typen, dann meine ich "erstelle die Klassen". Sie können sicher var oder was auch immer verwenden, aber es ist nur ein Compiler-Trick
Ewan