Warten Sie, welche Sprache ist das?

37

Kürzlich hatte ich das Vergnügen, ein Haskell-Programm zu schreiben, das erkennen konnte, ob die NegativeLiteralsErweiterung belegt war. Ich habe mir folgendes ausgedacht:

data B=B{u::Integer}
instance Num B where{fromInteger=B;negate _=B 1}
main=print$1==u(-1)

Probieren Sie es online!

Dies wird Truenormal und Falseansonsten gedruckt .

Jetzt hatte ich so viel Spaß dabei, dass ich die Herausforderung auf euch alle ausdehne. Welche anderen Haskell-Spracherweiterungen können Sie knacken?

Regeln

Um eine bestimmte Spracherweiterung zu knacken, müssen Sie ein Haskell-Programm schreiben, das mit und ohne Spracherweiterung kompiliert (Warnungen sind in Ordnung) und zwei verschiedene fehlerfreie Werte ausgibt , wenn es mit der Spracherweiterung ausgeführt und deaktiviert wird (durch Hinzufügen des NoPräfixes zu) die Spracherweiterung). Auf diese Weise könnte der obige Code auf Folgendes gekürzt werden:

data B=B{u::Integer}
instance Num B where{fromInteger=B;negate _=B 1}
main=print$u(-1)

welche druckt 1und -1.

Jede Methode, die Sie zum Knacken einer Erweiterung verwenden, muss für diese Erweiterung spezifisch sein. Es kann Möglichkeiten geben, willkürlich festzustellen, welche Compiler-Flags oder LanguageExtensions aktiviert sind, wenn solche Methoden nicht zulässig sind. Sie können zusätzliche Spracherweiterungen aktivieren oder die Compileroptimierung kostenlos -Oan Ihrer Byteanzahl ändern .

Spracherweiterungen

Sie können keine Spracherweiterung knacken, der keinen hat NoGegenstück (zB Haskell98, Haskell2010, Unsafe, Trustworthy, Safe) , da diese nicht unter den oben genannten Bedingungen fallen. Jede andere Spracherweiterung ist Freiwild.

Wertung

Sie erhalten einen Punkt für jede Spracherweiterung, die Sie als erste Person knacken, und einen zusätzlichen Punkt für jede Spracherweiterung, für die Sie den kürzesten (gemessen in Byte) Riss haben. Für den zweiten Punkt werden die Bande zugunsten früherer Einreichungen unterbrochen. Eine höhere Punktzahl ist besser

Sie können keinen Punkt für die erste Einreichung erzielen, NegativeLiteralsoder QuasiQuotesweil ich sie bereits geknackt und in den Inhalt des Beitrags aufgenommen habe. Sie werden jedoch in der Lage sein, einen Punkt für den kürzesten Riss von jedem von diesen zu erzielen. Hier ist mein Riss vonQuasiQuotes

import Text.Heredoc
main=print[here|here<-""] -- |]

Probieren Sie es online!

Weizen-Assistent
quelle
3
Ich denke, dies ist eine Liste aller gültigen Optionen
H.PWiz
1
Beachten Sie, dass mein obiger Kommentar NondecreasingIndentationaus offensichtlichen Gründen nicht enthalten
H.PWiz
4
Ich denke, dieser Titel ist irreführend, da die einzige Sprache, die Sie verwenden können, Haskell ist. Wie wäre es Wait, what language extension is this?Oder etwas ganz anderes.
MD XF
1
Ich bin ziemlich neugierig, ob es möglich ist zu knacken RelaxedPolyRec, für einen Compiler, der alt genug ist, um das Ausschalten tatsächlich zu unterstützen. (Die Option blieb mit der Dokumentation einige Jahre lang bestehen, nachdem sie aufgehört hatte, irgendetwas zu tun.)
7.
1
@dfeuer Wenn Sie sich dieses Ticket ansehen, scheint es, als ob GHC 6.12.1 es unterstützt, es auszuschalten.
Ørjan Johansen

Antworten:

24

MagicHash, 30 Bytes

x=1
y#a=2
x#a=1
main=print$x#x

-XMagicHash gibt 1 aus, -XNoMagicHash gibt 2 aus

Mit MagicHash können Variablennamen in a enden #. Daher mit der Erweiterung definiert diese beiden Funktionen y#und x#die jeweils einen Wert annehmen , und eine konstante Rück 2oder 1. x#xgibt 1 zurück (weil es x#angewendet wird 1)

Ohne die Erweiterung wird eine Funktion definiert, #die zwei Argumente akzeptiert und zurückgibt 2. Das x#a=1ist ein Muster, das niemals erreicht wird. Dann x#xist 1#1, was 2 zurückgibt.

H.PWiz
quelle
2
Ich singe jetzt X Magic Hash nach Dance Magic Dance . Ich hoffe du bist stolz!
TRiG
Ich bin erstaunt, MagicHashdass nicht nachgestellte Hashes nicht zulässig sind. Seltsam!
6.
18

CPP, 33 20 Bytes

main=print$0-- \
 +1

Druckt 0mit -XCPPund 1mit -XNoCPP.

Mit -XCPPeinem Schrägstrich \vor einer neuen Zeile wird die neue Zeile entfernt, so dass der Code main=print$0-- +1nur 0gedruckt wird, wenn er +1jetzt Teil des Kommentars ist.

Ohne das Flag wird der Kommentar ignoriert und die zweite Zeile wird als Teil der vorherigen Zeile analysiert, da sie eingerückt ist.


Vorheriger Ansatz mit #define

x=1{-
#define x 0
-}
main=print x

Druckt auch 0mit -XCPPund 1mit -XNoCPP.

Laikoni
quelle
2
Oh Gott, bis jetzt dachte ich, dass GHC Haskell-Kommentare streifen würde, bevor er zum CPP übergeht.
Cubic
@ Cubic Ist es kein Pre- Prozessor?
Bergi
1
@Bergi Sicher, aber Vorprozessoren bedeuten nicht unbedingt "ist das Erste, was ausgeführt wird", zumal GHC zuerst die Datei übergehen muss, um überhaupt das Pragma zu finden. Ich schätze, Kommentare bleiben erhalten, damit Doc-Kommentare und ähnliches funktionieren, nachdem CPP abgeschlossen ist.
Cubic
14

BinaryLiterals, 57 Bytes

b1=1
instance Show(a->b)where;show _=""
main=print$(+)0b1

-XBinaryLiterals gibt eine einzelne neue Zeile aus. -XNoBinaryLiterals druckt a 1.

Ich bin sicher, es gibt einen besseren Weg, dies zu tun. Wenn Sie einen finden, posten Sie ihn bitte.

H.PWiz
quelle
Kannst du nicht einfach bals Funktion definieren (also wird keine Binärdatei b(0, 1), sondern Binärdatei 0b1)?
NoOneIsHere
12

MonomorphismRestriction + 7 andere, 107 Bytes

Dies verwendet TH, wofür das Flag immer benötigt wird -XTemplateHaskell.

Datei T.hs, 81 + 4 Bytes

module T where
import Language.Haskell.TH
p=(+)
t=reify(mkName"p")>>=stringE.show

Haupt, 22 Bytes

import T
main=print $t

Das Kompilieren mit dem Flag MonomorphismRestriction erzwingt den Typ von pto Integer -> Integer -> Integerund erzeugt somit die folgende Ausgabe:

"VarI T.p (AppT (AppT ArrowT (ConT GHC.Integer.Type.Integer)) (AppT (AppT ArrowT (ConT GHC.Integer.Type.Integer)) (ConT GHC.Integer.Type.Integer))) Nothing"

Beim Kompilieren mit dem Flag NoMonomorphismRestriction bleibt der Typ von pam allgemeinsten, d. H. Num a => a->a->a- Herstellung von etwas wie (die VarTNamen verkürzt a):

"VarI T.p (ForallT [KindedTV a StarT] [AppT (ConT GHC.Num.Num) (VarT a)] (AppT (AppT ArrowT (VarT a)) (AppT (AppT ArrowT (VarT a)) (VarT a)))) Nothing"

Probiere sie online aus!


Alternativen

Da der obige Code einfach den Typ von pausgibt, kann dies mit allen Flags erfolgen, die irgendwie Einfluss darauf haben, wie Haskell Typen ableitet. Ich werde nur das Flag angeben und womit die Funktion zu ersetzen ist pund ggf. zusätzliche Flags (nebenbei -XTemplateHaskell):

OverloadedLists, 106 Bytes

Benötigt zusätzlich -XNoMonomorphismRestriction:

p=[]

Entweder p :: [a]oder p :: IsList l => l, versuchen Sie sie online!

OverloadedStrings, 106 Bytes

Benötigt zusätzlich -XNoMonomorphismRestriction:

p=""

Entweder p :: Stringoder p :: IsString s => s, versuchen Sie sie online!

PolyKinds, 112 Bytes

Dies ist ausschließlich @CsongorKiss zu verdanken:

data P a=P 

Entweder P :: P aoder P :: forall k (a :: k). P a, versuchen Sie sie online!

MonadComprehensions, 114 Byte

p x=[i|i<-x]

Entweder p :: [a] -> [a]oder p :: Monad m => m a -> m a, versuchen Sie sie online!

NamedWildCards, 114 Bytes

Diese wurde von @Laikoni gefunden und benötigt zusätzlich -XPartialTypeSignatures:

p=id::_a->_a

Beide haben den Speichertyp ( p :: a -> a), aber GHC generiert unterschiedliche Namen für die Variablen. Probieren Sie sie online aus!

ApplicativeDo, 120 Byte

p x=do i<-x;pure i

Entweder p :: Monad m => m a -> m aoder p :: Functor f => f a -> f a, versuchen Sie sie online!

OverloadedLabels, 120 Byte

Dies benötigt das zusätzliche Flag -XFlexibleContexts:

p x=(#id)x
(#)=seq

Entweder Typen wie p :: a -> b -> boder p :: IsLabel "id" (a->b) => a -> b, versuchen Sie sie online!

ბიმო
quelle
Funktioniert Ähnliches für andere Flags?
H.PWiz
Ja, du könntest es mit OverloadedStringsoder OverloadedListssicher und wahrscheinlich auch mit anderen machen.
21.
2
Es funktioniert auch mit PolyKinds: Online ausprobieren!
Csongor Kiss
1
Scheint auch zu funktionieren mit NamedWildCards: Online ausprobieren! (Erforderlich -XPartialTypeSignatures)
Laikoni
10

CPP, 27 25

main=print({-/*-}1{-*/-})

Probieren Sie es online!

Drucke ()für -XCPPund 1für-XNoCPP

Vorherige Version:

main=print[1{-/*-},2{-*/-}]

Probieren Sie es online!

Druckt [1]mit -XCPPund [1,2]anders.

Credits: Dies ist von der Antwort von Laikoni inspiriert, verwendet aber statt eines #defineeinfach C-Kommentare.

Celtschk
quelle
9

ScopedTypeVariables, 162 - 113 Byte

instance Show[()]where show _=""
p::forall a.(Show a,Show[a])=>a->IO()
p a=(print::Show a=>[a]->IO())[a]
main=p()

-XScopedTypeVariables druckt ""(leer), -XNoScopedTypeVariables druckt "[()]".

Edit: aktualisierte Lösung dank nützlicher Vorschläge in den Kommentaren

Csongor Kiss
quelle
1
Ah ich sehe. Es ist im Allgemeinen besser, den Code in den Body aufzunehmen, aber auch ungolfederte Versionen sind gut. Mir ist auch aufgefallen, dass "T"nur durch ersetzt werden kann "".
Weizen-Zauberer
2
Sie können Ihren Datentyp auch Tdurch ersetzen (). Um es nicht definieren zu müssen. Probieren Sie es online!
Weizen-Zauberer
1
Guter Fang, mir ist gerade aufgefallen, dass das inkohärente Pragma als Fahne verwendet werden kann: Probieren Sie es online aus!
Csongor Kiss
2
show Kann für Druck
H.PWiz
Mit der Unicode-Syntax für forallsparen Sie einige Bytes. Ich bezweifle, dass jede Lösung, die zusätzliche Instanzen benötigt, viel Hoffnung auf einen Sieg hat.
7.
9

MonoLocalBinds, GADTs oder TypeFamilies, 36 32 Bytes

BEARBEITEN:

  • -4 Bytes: Eine Version davon wurde von stasoid in die große polyglotte Kette aufgenommen, die mich überraschte, indem sie alle Deklarationen auf die oberste Ebene stellte. Anscheinend erfordert das Auslösen dieser Einschränkung keine tatsächlichen lokalen Bindungen.
a=0
f b=b^a
main=print(f pi,f 0)
  • Mit ohne Erweiterungen , druckt dieses Programm (1.0,1).
  • Mit den Flags -XMonoLocalBinds , -XGADTs oder -XTypeFamilies wird gedruckt (1.0,1.0).

  • Die MonoLocalBindsErweiterung soll verhindern, dass durch GADTs und Typfamilien eine nicht intuitive Typinferenz ausgelöst wird. Daher wird diese Erweiterung von den beiden anderen automatisch aktiviert.

  • Es ist möglich, es explizit mit wieder auszuschalten -XNoMonoLocalBinds, dieser Trick geht davon aus, dass Sie dies nicht tun.
  • Wie seine bekanntere Cousine, die Monomorphismus-Beschränkung, MonoLocalBindsverhindert sie, dass einige Werte ( in lokalen Bindungen wie letoder where, daher kann der Name anscheinend auch auf oberster Ebene vorkommen) polymorph sind. Die Regeln für den Zeitpunkt der Auslösung sind, obwohl sie für eine genauere Typinferenz erstellt wurden, nach Möglichkeit noch haariger als die MR.

  • Das obige Programm fügt den Typ ohne Erweiterung ein und f :: Num a => a -> aerlaubt f pistandardmäßig a Doubleund f 0an Integer.

  • Mit den Erweiterungen wird der Typ abgeleitet f :: Double -> Doubleund f 0muss Doubleauch a zurückgeben.
  • Die separate Variable a=0wird benötigt, um die technischen Regeln auszulösen: aWird von der Monomorphismus-Beschränkung getroffen und aist eine freie Variable von f, was bedeutet, dass fdie Bindungsgruppe nicht vollständig verallgemeinert ist , dh fnicht geschlossen ist und daher nicht polymorph wird.
Ørjan Johansen
quelle
9

OverloadedStrings, 65 48 32 Bytes

Verwenden Sie unter Ausnutzung von RebindableSyntax unsere eigene Version von fromString, um jedes String-Literal in zu verwandeln "y".

main=print""
fromString _=['y']

Muss mit kompiliert werden -XRebindableSyntax -XImplicitPrelude.

Ohne -XOverloadedStringsDrucke ""; mit drucke "y".

Außerdem ist mir erst jetzt aufgefallen, dass die gleiche Technik mit (zB) OverloadedLists funktioniert:

OverloadedLists, 27 Bytes

main=print[0]
fromListN=(:)

Muss mit kompiliert werden -XRebindableSyntax -XImplicitPrelude.

Ohne -XOverloadedListsDrucke [0]; mit drucke [1,0].

felixphew
quelle
1
Sie können die letzte Zeile auf kürzen fromString a=['y'].
Ørjan Johansen
Der Raum in print "n"kann auch fallen gelassen werden.
Laikoni
@ ØrjanJohansen danke! Ich hatte es nicht mit ="y", aber =['y']funktioniert gut!
Felixphew
1
Sie können die zweite nvon entfernenprint"n"
Weizen-Assistent
1
Sie können auch -XImplicitPreludenach verwenden RebindableSyntax, um die Importzeile zu umgehen.
6.
8

BangPatterns, 32 Bytes

(!)=seq
main|let f!_=0=print$9!1

-XBangPatterns druckt 1während -XNoBangPatterns druckt 0.

Dies macht Gebrauch davon, dass das Flag BangPatterns erlaubt, Muster mit Anmerkungen zu versehen !, um die Auswertung an WHNF zu erzwingen. In diesem Fall 9!1wird die Definition der obersten Ebene verwendet (!)=seq. Wenn das Flag nicht aktiviert f!_ist, wird ein neuer Operator definiert (!)und die Definition der obersten Ebene abgeschattet.

ბიმო
quelle
7

ApplicativeDo, 104 Byte

import Control.Applicative
z=ZipList
instance Monad ZipList where _>>=_=z[]
main=print$do a<-z[1];pure a

Probieren Sie es online!

Mit ApplicativeDowird dies gedruckt

ZipList {getZipList = [1]}

Ohne es druckt es

ZipList {getZipList = []}

ZipListist einer der wenigen Typen in den Basisbibliotheken mit einer Instanz für, Applicativeaber nicht für Monad. Es kann kürzere Alternativen geben, die irgendwo lauern.

Zgarb
quelle
7

Streng, 87 84 82 Bytes

-5 bytes dank dfeuer !

Könnte weniger mit dem BlockArgumentsSpeichern der Eltern herum sein \_->print 1:

import Control.Exception
0!_=0
main=catch @ErrorCall(print$0!error"")(\_->print 1)

Wird dies mit -XStrict ausgeführt, wird ein ausgegeben , 1während bei Ausführung mit -XNoStrict ein ausgegeben wird 0. In diesem Fall ist Haskell standardmäßig faul und muss nicht ausgewertet werden, error""da bereits bekannt ist, dass das Ergebnis 0bei Übereinstimmung mit dem ersten Argument von angezeigt wird. (!)Dieses Verhalten kann mit diesem Flag geändert werden, sodass die Laufzeit beide Argumente auswerten muss.

Wenn in einem Fall nichts gedruckt werden darf, können wir es auf 75 Bytes reduzieren , indem wir das Hauptbyte ersetzen (auch einige Bytes von dfeuer ):

main=catch @ErrorCall(print$0!error"")mempty

StrictData, 106 99 93 Bytes

-15 bytes dank dfeuer !

Dies funktioniert im Prinzip genauso, funktioniert jedoch stattdessen mit Datenfeldern:

import Control.Exception
data D=D()
main=catch @ErrorCall(p$seq(D$error"")0)(\_->p 1);p=print

Druck 1mit der -XStrictData Flagge und 0mit -XNoStrictData .

Wenn in einem Fall nichts gedruckt werden darf, können wir es auf 86 Bytes reduzieren, wobei das Hauptbyte durch (19 Bytes durch dfeuer ) ersetzt wird:

main=catch @ErrorCall(print$seq(D$error"")0)mempty

Hinweis: Alle Lösungen müssen TypeApplicationsfestgelegt werden.

ბიმო
quelle
Sie können dies ziemlich einfach auf 98 Bytes reduzieren, was meiner (sehr unterschiedlichen) Lösung genau entspricht. TIO .
7.
Eigentlich können Sie es sogar noch besser machen: Anstatt im Ausnahmehandler zu drucken, verwenden Sie einfach pure().
7.
1
@dfeuer: Schön, der D{}Trick ist ziemlich cool! Rasiert eine andere von mit PartialTypeSignaturesanstelle von ScopedTypeVariables:)
ბიმო
1
@dfeuer: Ich habe nachgesehen und ein paar Dinge ausprobiert, aber ich habe nie Generics verwendet, daher bin ich wahrscheinlich nicht die richtige Person.
8.
1
Du kannst es noch besser machen mit GHC und -XBlockArguments:main=catch @ErrorCall(p$seq(D$error"")1)\_->p 3
dfeuer
6

ApplicativeDo, 146 Bytes

newtype C a=C{u::Int}
instance Functor C where fmap _ _=C 1
instance Applicative C
instance Monad C where _>>=_=C 0
main=print$u$do{_<-C 0;pure 1}

Gibt 1 aus, wenn ApplicativeDo aktiviert ist, andernfalls 0

Probieren Sie es online!

oisdk
quelle
1
Vielen Dank! Ah, ich denke, ich bin auf einer älteren Version von GHC (das "no applicative" war eine Warnung auf meinem System)
oisdk
3
Mit -XDeriveAnyClass Sie ableiten können Applicativeund Showmit Rekord - Syntax zu speichern, finden Sie diese .
22.
6

BinaryLiterals, 31 24 Bytes

Bearbeiten:

  • -7 Bytes: H.PWiz schlug vor, die Einstellung mithilfe einer einzelnen b12Variablen weiter anzupassen .

Eine Anpassung der Methode von H.PWiz unter Vermeidung der Funktionsinstanz.

b12=1
main=print$(+)0b12
Ørjan Johansen
quelle
6

ExtendedDefaultRules, 54 53 Bytes

instance Num()
main=print(toEnum 0::Num a=>Enum a=>a)

Druckt ()mit -XExtendedDefaultRulesund 0mit -XNoExtendedDefaultRules.

Dieses Flag ist standardmäßig in GHCi aktiviert, aber nicht in GHC, was kürzlich einige Verwirrung bei mir ausgelöst hat , obwohl BMO schnell helfen konnte.

Der obige Code ist eine Golfversion eines Beispiels im GHC-Benutzerhandbuch, in dem der in GHCi voreingestellte Typ erläutert wird.

-1 Byte danke an Ørjan Johansen !

Laikoni
quelle
Als ich mir diesen Code ansah, der in den Polyglot entlehnt war (wo die Klammern Probleme bereiten), fiel mir ein, dass GHC die um ein Byte kürzere Syntax unterstützt toEnum 0::Num a=>Enum a=>a.
Ørjan Johansen
Sie können es bis zu 48 Bytes runter mit PartialTypeSignatures: main=print(toEnum 0::_=>Num a=>a). Außerdem ist Ihr TIO-Link nicht mehr aktuell.
7.
6

RebindableSyntax , 25 Byte

Ich habe gerade den kürzlich veröffentlichten Leitfaden zu den Erweiterungen von GHC gelesen, als mir ein einfacher Leitfaden aufgefallen ist, den ich hier noch nicht gesehen habe.

main|negate<-id=print$ -1

Benötigt -XImplicitPreludeauch oder alternativ import Preludeim Code selbst.

  • -XRebindableSyntax ändert das Verhalten einiger syntaktischer Zucker von Haskell, um eine Neudefinition zu ermöglichen.
  • -1ist syntaktischer Zucker für negate 1.
  • Normalerweise dies negateist Prelude.negate, aber mit der Erweiterung ist es „je nachdem , was negatean der Verwendungsstelle in ihrem Umfang ist“, die definiert ist als id.
  • Da die Erweiterung zum Ersetzen des PreludeModuls verwendet werden soll, wird der normale implizite Import des Moduls automatisch deaktiviert, jedoch werden hier andere PreludeFunktionen (wie print) benötigt, sodass es mit erneut aktiviert wird -XImplicitPrelude.
Ørjan Johansen
quelle
6

Streng, 52 Bytes

import GHC.IO
f _=print()
main=f$unsafePerformIO$f()

-XStrict

-XNoStrict

Mit -XStrictwird ()eine zusätzliche Zeit gedruckt .

Vielen Dank an @Sriotchilism O'Zaic für zwei Bytes.

dfeuer
quelle
6

StrictData, 58 Bytes

import GHC.Exts
data D=D Int
main=print$unsafeCoerce#D 3+0

(Links sind etwas veraltet; wird behoben.)

-XNoStrictData

-XStrictData

Benötigt MagicHash( GHC.Extsstatt importieren zu lassen Unsafe.Coerce) und -O(unbedingt erforderlich, um das Auspacken kleiner, strenger Felder zu ermöglichen).

Mit -XStrictDatawird 3 ausgegeben. Andernfalls wird der ganzzahlige Wert des (wahrscheinlich gekennzeichneten) Zeigers auf die vorab zugewiesene Kopie von gedruckt 3::Integer, die möglicherweise nicht 3 sein kann.

Erläuterung

Es wird ein bisschen einfacher, mit einer kleinen Erweiterung zu verstehen, basierend auf dem Standardtyp. Mit Unterschriften können wir den Zusatz verwerfen.

main=print
  (unsafeCoerce# D (3::Integer)
    :: Integer)

Äquivalent dazu

main=print
  (unsafeCoerce# $
    D (unsafeCoerce# (3::Integer))
    :: Integer)

Warum druckt es jemals 3? Das scheint überraschend! Nun, kleine IntegerWerte werden sehr ähnlich wie Ints dargestellt, die (mit strengen Daten) genau wie Ds dargestellt werden. Am Ende ignorieren wir das Tag, das angibt, ob die Ganzzahl klein oder groß positiv / negativ ist.

Warum kann 3 nicht ohne die Erweiterung gedruckt werden? Abgesehen von Speicherlayoutgründen muss ein Datenzeiger mit niedrigen Bits (2 niedrigste für 32-Bit, 3 niedrigste für 64-Bit) von 3 einen Wert darstellen, der aus dem dritten Konstruktor erstellt wurde. In diesem Fall würde dies eine negative ganze Zahl erfordern .

dfeuer
quelle
5

UnboxedTuples, 52 Bytes

import Language.Haskell.TH
main=runQ[|(##)|]>>=print

Benötigt -XTemplateHaskell. Drucke ConE GHC.Prim.(##)mit -XUnboxedTuples und UnboundVarE ##mit -XNoUnboxedTuples .

Laikoni
quelle
Sollte die Punktzahl für die gewünschte Option nicht noch +16 betragen -XTemplateHaskell?
Celtschk
2
@celtschk Ich habe es nicht gezählt, weil der aktuelle Metakonsens für Befehlszeilenflags besagt, dass sie nicht gezählt werden, sondern stattdessen eine neue Sprache darstellen. Wenn ich darüber nachdenke, sehe ich, dass im Kontext dieser Herausforderung, die nur Haskell-Antworten, aber auch die Verwendung anderer Flags ermöglicht, nicht ganz klar ist, was zu tun ist. Ich werde OP danach fragen.
Laikoni,
Mir war nicht bewusst, dass sich der Konsens diesbezüglich geändert hat. Danke für den Hinweis. Das OP zu fragen ist auf jeden Fall eine gute Idee.
Celtschk
5

OverloadedLists, 76 Bytes

import GHC.Exts
instance IsList[()]where fromList=(():)
main=print([]::[()])

Mit -XOverloadedLists wird gedruckt [()]. Mit -XNoOverloadedLists wird gedruckt[]

Dies erfordert die zusätzliche Fahnen: -XFlexibleInstances,-XIncoherentInstances

H.PWiz
quelle
Sie können mit überlappenden Instanzen davonkommen.
7.
5

HexFloatLiterals , 49 25 Bytes

-24 Bytes dank Ørjan Johansen.

main|(.)<-seq=print$0x0.0

Druckt 0.0mit -XHexFloatLiteralsund 0mit -XNoHexFloatLiterals.

Es gibt keine TIO-Links, da HexFloatLiterals in Ghc 8.4.1 hinzugefügt wurde, TIO jedoch Ghc 8.2.2.

stasoid
quelle
main|(.)<-seq=print$0x0.0vermeidet das Ausblenden des Imports.
Ørjan Johansen
main|let _._=0=print$0x0.0könnte jedoch für die Mehrsprachigkeit einfacher sein.
Ørjan Johansen
5

ScopedTypeVariables, 37 Byte

main=print(1::_=>a):: a.a~Float=>_

Dies erfordert auch UnicodeSyntax, PartialTypeSignatures, GADTs, und ExplicitForAll.

Probieren Sie es online (ohne Erweiterung)

Probieren Sie es online (mit Erweiterung)

Erläuterung

Die partiellen Typ-Signaturen dienen nur zum Speichern von Bytes. Wir können sie folgendermaßen ausfüllen:

main=print(1::(Num a, Show a)=>a):: a.a~Float=>IO ()

Mit scoped Typ Variablen, die avon in der Art 1beschränkt ist , die zu sein ain der Art der main, der sich gezwungen ist , zu sein Float. Ohne Typvariablen mit Gültigkeitsbereich wird 1standardmäßig der Typ verwendet Integer. Da Floatund IntegerWerte unterschiedlich dargestellt werden, können wir sie unterscheiden.

Vielen Dank an @ ØrjanJohansen für satte 19 Bytes! Er erkannte, dass es viel besser war, den Unterschied zwischen ShowInstanzen verschiedener numerischer Typen auszunutzen, als Unterschiede in ihrer Arithmetik. Er erkannte auch, dass es in Ordnung war, den Typ main"syntaktisch mehrdeutig" zu belassen, da die Einschränkung ihn tatsächlich eindeutig macht. Durch das Entfernen der lokalen Funktion konnte ich auch die Typensignatur für entfernen main(auf RHS verschieben), um fünf weitere Bytes zu sparen.

dfeuer
quelle
45 Bytes
Ørjan Johansen
@ ØrjanJohansen, schön .
7.
@ ØrjanJohansen, soll ich die Bearbeitung vornehmen, oder möchtest du lieber deine eigene hinzufügen?
7.
Edit, es war eine schrittweise Weiterentwicklung von dir.
Ørjan Johansen
@ ØrjanJohansen, danke, das war schön.
7.
5

DeriveAnyClass, 121 113 Bytes

Danke an dfeuer für etliche Bytes!

import Control.Exception
newtype M=M Int deriving(Show,Num)
main=handle h$print(0::M);h(_::SomeException)=print 1

-XDeriveAnyClass druckt, 1wohingegen -XNoDeriveAnyClass druckt M 0.

Dies nutzt die Tatsache aus, dass DeriveAnyClass die Standardstrategie ist, wenn DeriveAnyClass und GeneralizedNewtypeDeriving aktiviert sind, wie Sie anhand der Warnungen sehen können. Dieses Flag generiert problemlos leere Implementierungen für alle Methoden, aber GeneralizedNewtypeDeriving ist tatsächlich intelligent genug, um die Implementierung des zugrunde liegenden Typs zu verwenden, und da dies Intein NumFehler ist , wird es in diesem Fall nicht fehlschlagen.


Wenn für den Fall, dass das Flag aktiviert ist, nichts gedruckt wird, beträgt das Ersetzen mainder folgenden Werte 109 Byte :

main=print(0::M)`catch`(mempty::SomeException->_)
ბიმო
quelle
Zumindest in runhaskell, dies tatsächlich druckt M 1mit -XDeriveAnyClass, aus Faulheit ...
aufgehört, gegen den Uhrzeigersinn am
@ceasedtoturncounterclockwis: Ja, auch in GHCi, aber beim Kompilieren auf TIO (und meinem Computer) und dann beim Ausführen ergibt sich 1:)
ბიმო
113 bytes
dfeuer
109 bytes
dfeuer
1
Ich habe es auf eine ganz andere Art und Weise auf 104 gebracht, also habe ich meine eigene Antwort hinzugefügt.
8.
4

PostfixOperators, 63 Bytes

import Text.Show.Functions
instance Num(a->b)
main=print(0`id`)

Probieren Sie es online (ohne Erweiterung)

Probieren Sie es online (mit Erweiterung)

Dies ist eine gekürzte Version eines von mir geschriebenen Hugs / GHC-Polyglots . In diesem Beitrag finden Sie eine Erklärung. Dank @ ØrjanJohansen für die Realisierung, dass ich idanstelle eines benutzerdefinierten Operators vier Bytes einsparen konnte.

dfeuer
quelle
idkann anstelle von verwendet werden !.
Ørjan Johansen
@ ØrjanJohansen, ja in der Tat! Das spart coole vier Bytes.
7.
3

TemplateHaskell, 140 91 Bytes

Nur mit kleinen Modifikationen von Mauke kopiert . Ich weiß nicht, was los ist.

-49 Bytes dank Ørjan Johansen.

import Language.Haskell.TH
instance Show(Q a)where show _=""
main=print$(pure$TupE[]::ExpQ)

Probieren Sie es online!

stasoid
quelle
$(...)(kein Leerzeichen) ist die Syntax für die Vorlagenbewertung, wenn TH aktiviert ist, und TupE[]("leeres Tupel") gibt (). Die Verwendung vonShow könnte für die Mehrsprachigkeit gut funktionieren, obwohl ich für diese besondere Herausforderung ein wenig schlecht darin bin, einen Wert als leere Zeichenfolge zu definieren ...
Ørjan Johansen
2

MonomorphismRestriction, 31 29 Bytes

Bearbeiten:

  • -2 Bytes mit einer Verbesserung von H.PWiz
f=(2^)
main=print$f$f(6::Int)

-XMonomorphismRestriction druckt 0. -XNoMonomorphismRestriction druckt 18446744073709551616.

  • Mit dieser Einschränkung müssen die beiden Verwendungen von fdenselben Typ haben, sodass das Programm 2^2^6 = 2^64als 64-Bit-Version Int(auf 64-Bit-Plattformen) gedruckt wird , die überläuft 0.
  • Ohne Einschränkung wird das Programm 2^64als Bignum gedruckt Integer.
Ørjan Johansen
quelle
1
Ich denke, f=(2^);main=print$f$f(64::Int)würde ein Byte sparen. Aber es wird nicht realistisch enden
H.PWiz
@ H.PWiz Zum Glück 64=2^6spart das noch ein Byte.
Ørjan Johansen
1

ScopedTypeVariables, 119 97 Bytes

Nur mit kleinen Modifikationen von Mauke kopiert .

Derzeit gibt es zwei weitere Antworten für ScopedTypeVariables: 113 Bytes von Csongor Kiss und 37 Bytes von dfeuer . Diese Übermittlung unterscheidet sich darin, dass keine anderen Haskell-Erweiterungen erforderlich sind.

-22 Bytes dank Ørjan Johansen.

class(Show a,Num a)=>S a where s::a->IO();s _=print$(id::a->a)0
instance S Float
main=s(0::Float)

Probieren Sie es online!

stasoid
quelle
97 Bytes (obwohl der IO()/printTrick im Polyglott nicht funktioniert).
Ørjan Johansen
@ ØrjanJohansen Ich habe ScopedTypeVariables hinzugefügt, aber ExtendedDefaultRules verletzt . Wie kann es behoben werden? Ich hatte bereits einen solchen Fehler, aber ich kann Ihre Erklärung hier nicht anwenden. Der ScopedTypeVariables-Code, den ich hinzugefügt habe, ist dieser .
Stasoid
Ich sehe, die Codes verwenden ähnliche Standardtricks und sie stören sich gegenseitig. Eine Lösung besteht darin, die neue Klasse eine eingeschränktere Klasse als verwenden zu lassen Num. Ich denke class(Show a,Floating a)=>K a where{k::a->String;k=pure$ show(f pi)where f=id::a->a};sollte funktionieren, das bequem nutzen Floatund mit unterschiedlicher Präzision Doubleanzeigen pi.
Ørjan Johansen
@ ØrjanJohansen Wow, es passt genau dazu. Danke.
Stasoid