Attends, quelle langue est-ce?

37

Récemment, j'ai eu le plaisir d'écrire un programme Haskell capable de détecter si l' NegativeLiteralsextension était activée. Je suis venu avec ce qui suit:

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

Essayez-le en ligne!

Cela imprimera Truenormalement et Falsesinon.

Maintenant, je me suis tellement amusé à faire que je vous lance un défi à tous. Quelles autres extensions de langage Haskell pouvez-vous craquer?

Règles

Pour déchiffrer une extension de langue particulière, vous devez écrire un programme Haskell qui compile à la fois avec et sans extension de langue (les avertissements conviennent) et génère deux valeurs différentes sans erreur lorsqu’elle est exécutée avec l’extension de langue et désactivée (en ajoutant le Nopréfixe à l'extension de langue). De cette façon, le code ci-dessus pourrait être réduit à seulement:

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

qui imprime 1et -1.

Toute méthode utilisée pour craquer une extension doit être spécifique à cette extension. Il peut exister des moyens de détecter arbitrairement quels indicateurs du compilateur ou LanguageExtensions sont activés, si de telles méthodes ne sont pas autorisées. Vous pouvez activer des extensions de langue supplémentaires ou modifier l'optimisation du compilateur en utilisant -Ogratuitement le nombre d'octets.

Extensions de langue

Vous ne pouvez pas casser toute extension de langage qui ne dispose pas d' une Nocontrepartie (par exemple Haskell98, Haskell2010, Unsafe, Trustworthy, Safe) car ceux - ci ne tombent pas dans les conditions décrites ci - dessus. Toute autre extension linguistique est un jeu équitable.

Notation

Vous recevrez un point pour chaque extension de langue que vous êtes la première personne à craquer et un point supplémentaire pour chaque extension de langue pour laquelle vous avez la fissure la plus courte (mesurée en octets). Pour le deuxième point, les liens seront brisés en faveur des soumissions précédentes. Plus le score est élevé, mieux c'est

Vous ne serez pas en mesure de marquer un point pour la première soumission NegativeLiteralsou QuasiQuotesparce que je les ai déjà craquées et les ai incluses dans le corps du message. Vous pourrez cependant marquer un point pour la fissure la plus courte de chacune d’elles. Voici ma fente deQuasiQuotes

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

Essayez-le en ligne!

Assistant de blé
la source
3
Je pense que ceci est une liste de toutes les options valides.
H.PWiz
1
Notez que mon commentaire ci-dessus n'inclut pas NondecreasingIndentationpour des raisons évidentes
H.PWiz
4
Je pense que ce titre est trompeur, car le seul langage que vous pouvez utiliser est Haskell. Que diriez - vous Wait, what language extension is this?ou quelque chose de complètement différent.
MD XF
1
Je suis assez curieux de savoir s'il est possible de se fissurer RelaxedPolyRec, pour un compilateur assez ancien pour réellement soutenir le mettre hors tension. (L'option a traîné, avec documentation, pendant quelques années après avoir cessé de faire quoi que ce soit.)
dfeuer
1
@dfeuer En regardant ce billet, il semble que GHC 6.12.1 était en mesure de l'éteindre.
Ørjan Johansen

Réponses:

24

MagicHash, 30 octets

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

-XMagicHash sorties 1, -XNoMagicHash sorties 2

MagicHash permet aux noms de variables de se terminer par a #. Donc avec l'extension, cela définit deux fonctions y#et x#qui prennent chacune une valeur et retournent une constante 2, ou 1. x#xretournera 1 (car il est x#appliqué à 1)

Sans l'extension, cela définit une fonction #qui prend deux arguments et retourne 2. Le x#a=1est un modèle qui n'est jamais atteint. Alors x#xest 1#1, qui retourne 2.

H.PWiz
la source
2
Je chante maintenant X Magic Hash sur l'air de Dance Magic Dance . J'espère que tu es fier!
TRiG
Je suis étonné que MagicHashles hachages ne soient pas perdus. Bizarre!
dfeuer
18

CPP, 33 à 20 octets

main=print$0-- \
 +1

Imprime 0avec -XCPPet 1avec -XNoCPP.

Avec -XCPP, une barre oblique \avant une nouvelle ligne supprime la nouvelle ligne, ainsi le code devient main=print$0-- +1et 0est uniquement imprimé, car il +1fait maintenant partie du commentaire.

Sans l'indicateur, le commentaire est ignoré et la deuxième ligne est analysée comme faisant partie de la ligne précédente car elle est en retrait.


Approche précédente avec #define

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

Imprime aussi 0avec -XCPPet 1avec -XNoCPP.

Laikoni
la source
2
Oh mon Dieu, je pensais jusqu'à présent que GHC effacerait les commentaires de Haskell avant de passer au RPC.
Cubes
@Cubic N'est-ce pas un pré- processeur?
Bergi
1
@Bergi Bien sûr, mais pré -processors ne signifie pas nécessairement « est la première chose qui fonctionne », d' autant plus que GHC doit faire une passe sur le fichier pour trouver même le pragma. Je suppose que les commentaires sont conservés dans les commentaires doc et le même travail une fois le RPC terminé.
Cubique
14

BinaryLiterals, 57 bytes

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

-XBinaryLiterals imprime une nouvelle ligne. -XNoBinaryLiterals imprime a 1.

Je suis sûr qu'il existe un meilleur moyen de le faire. Si vous en trouvez un, merci de le poster.

H.PWiz
la source
Ne pouvez-vous pas simplement définir en btant que fonction (aucun binaire ne devient b(0, 1), mais binaire devient 0b1)?
NoOneIsHere le
12

MonomorphismRestriction + 7 others, 107 bytes

Cela utilise TH qui nécessite le drapeau -XTemplateHaskellà tout moment.

Fichier T.hs, 81 + 4 octets

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

Main, 22 octets

import T
main=print $t

La compilation avec l'indicateur MonomorphismRestriction force le type de pto Integer -> Integer -> Integeret produit ainsi le résultat suivant:

"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"

Compiler avec le drapeau NoMonomorphismRestriction laisse le type pau plus général, c'est-à-dire. Num a => a->a->a- produire quelque chose comme (abrégé les VarTnoms 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"

Essayez-les en ligne!


Des alternatives

Puisque le code ci-dessus affiche simplement le type de p, cela peut être fait avec tous les indicateurs qui influencent d'une manière ou d'une autre la façon dont Haskell déduit les types. Je ne spécifierai que le drapeau et avec quoi remplacer la fonction pet si nécessaire des drapeaux supplémentaires (à part -XTemplateHaskell):

OverloadedLists, 106 octets

De plus, il faut -XNoMonomorphismRestriction:

p=[]

Ou p :: [a]bien p :: IsList l => l, essayez-les en ligne!

OverloadedStrings, 106 octets

De plus, il faut -XNoMonomorphismRestriction:

p=""

Ou p :: Stringbien p :: IsString s => s, essayez-les en ligne!

PolyKinds, 112 octets

Ceci est entièrement dû à @CongorKiss:

data P a=P 

Ou P :: P abien P :: forall k (a :: k). P a, essayez-les en ligne!

MonadComprehensions, 114 octets

p x=[i|i<-x]

Ou p :: [a] -> [a]bien p :: Monad m => m a -> m a, essayez-les en ligne!

NamedWildCards, 114 octets

Celui-ci a été trouvé par @Laikoni, il nécessite en plus -XPartialTypeSignatures:

p=id::_a->_a

Ils ont tous les deux le type de sauvegarde ( p :: a -> a) mais GHC génère des noms différents pour les variables, essayez-les en ligne!

ApplicativeDo, 120 octets

p x=do i<-x;pure i

Ou p :: Monad m => m a -> m abien p :: Functor f => f a -> f a, essayez-les en ligne!

OverloadedLabels, 120 octets

Cela nécessite le drapeau supplémentaire -XFlexibleContexts:

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

Soit comme p :: a -> b -> bou p :: IsLabel "id" (a->b) => a -> b, essayez-les en ligne!

ბიმო
la source
Est-ce qu'une chose semblable fonctionne pour d'autres drapeaux?
H.PWiz
Oui, vous pouvez le faire avec OverloadedStringsou OverloadedListssûr et probablement d' autres aussi ..
ბიმო
2
Cela fonctionne aussi avec PolyKinds: Essayez-le en ligne!
Csongor Kiss
1
Semble également fonctionner avec NamedWildCards: essayez-le en ligne! (Requis -XPartialTypeSignatures)
Laikoni
10

CPP, 27 25

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

Essayez-le en ligne!

Gravures ()pour -XCPPet 1pour-XNoCPP

La version précédente:

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

Essayez-le en ligne!

Imprime [1]avec -XCPPet [1,2]autrement.

Crédits: Ceci est inspiré de la réponse de Laikoni, mais au lieu de #definecela, il utilise simplement des commentaires C.

celtschk
la source
9

ScopedTypeVariables, 162 113 octets

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

-XScopedTypeVariables imprime ""(vide), -XNoScopedTypeVariables imprime "[()]".

Edit: solution mise à jour grâce aux suggestions utiles dans les commentaires

Csongor Kiss
la source
1
Ah, je vois. Il est généralement plus agréable d’inclure votre code dans le corps, mais les versions non golfées sont bien aussi. Je remarque également que cela "T"peut simplement être remplacé par "".
Wheat Wizard
2
Une autre chose que vous pouvez faire est de remplacer votre type Tde données par (). Pour éviter d'avoir à le définir. Essayez-le en ligne!
Wheat Wizard
1
Belle prise, je viens de me rendre compte que le pragma incohérent peut être inclus en tant que drapeau: essayez-le en ligne!
Csongor Kiss
2
En outre, show peut être modifié pour impression
H.PWiz
La syntaxe Unicode pour vous forallfera économiser quelques octets. Je doute que toute solution nécessitant des instances supplémentaires ait beaucoup d’espoir de gagner.
dfeuer
9

MonoLocalBinds, GADT ou TypeFamilies, 36 32 octets

MODIFIER:

  • -4 octets: une version de celui-ci a été intégrée à la grande chaîne polyglotte par stasoid, qui m'a surpris en plaçant toutes les déclarations au plus haut niveau. Apparemment, le déclenchement de cette restriction ne nécessite pas de liaisons locales réelles .
a=0
f b=b^a
main=print(f pi,f 0)
  • Sans extensions , ce programme imprime (1.0,1).
  • Avec l'un des indicateurs -XMonoLocalBinds , -XGADTs ou -XTypeFamilies , il s'imprime (1.0,1.0).

  • L' MonoLocalBindsextension existe pour empêcher toute inférence de type non intuitive déclenchée par les GADT et les familles de types. En tant que telle, cette extension est automatiquement activée par les deux autres.

  • Il est possible de le désactiver explicitement avec -XNoMonoLocalBinds, cette astuce suppose que vous ne le faites pas.
  • Comme son cousin plus connu, la restriction de monomorphisme, MonoLocalBindsempêche certaines valeurs ( dans les liaisons locales telles que letou where, ainsi le nom semble aussi arriver au plus haut niveau) d’être polymorphes. Bien qu’elles aient été créées pour des inférences de type plus sain, les règles régissant les déclencheurs sont, si possible, encore plus difficiles que le MR.

  • Sans aucune extension, le programme ci-dessus déduit le type f :: Num a => a -> a, permettant f pide définir par défaut un Doubleet f 0un Integer.

  • Avec les extensions, le type inféré devient f :: Double -> Doubleet f 0doit lui aussi être renvoyé Double.
  • La variable séparée a=0est nécessaire pour déclencher les règles techniques: aest frappée par la restriction de monomorphisme et aest une variable libre de f, ce qui signifie que fle groupe de liaisons de ce dernier n'est pas complètement généralisé , ce qui signifie qu'il fn'est pas fermé et ne devient donc pas polymorphe.
Ørjan Johansen
la source
9

OverloadedStrings, 65 48 32 octets

Tirant parti de RebindableSyntax, utilisez notre propre version de fromString pour transformer tout littéral de chaîne en "y".

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

Doit être compilé avec -XRebindableSyntax -XImplicitPrelude.

Sans -XOverloadedStringsimpressions ""; avec des impressions "y".

En outre, je viens tout juste de penser que la même technique fonctionne avec (par exemple) OverloadedLists:

OverloadedLists, 27 octets

main=print[0]
fromListN=(:)

Doit être compilé avec -XRebindableSyntax -XImplicitPrelude.

Sans -XOverloadedListsimpressions [0]; avec des impressions [1,0].

Felixphew
la source
1
Vous pouvez raccourcir la dernière ligne à fromString a=['y'].
Ørjan Johansen
L'espace print "n"peut également être supprimé.
Laikoni
@ ØrjanJohansen merci! Je le faisais échouer avec ="y", mais ça =['y']fonctionne bien!
felixphew le
1
Vous pouvez supprimer la seconde ndeprint"n"
Wheat Wizard
1
Vous pouvez également utiliser -XImplicitPreludeaprès RebindableSyntaxpour éviter la ligne d'importation.
dfeuer
8

BangPatterns, 32 octets

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

-XBangPatterns imprime 1alors que -XNoBangPatterns imprimera 0.

Cela permet d’utiliser le drapeau que BangPatterns permet d’annoter des modèles avec !pour forcer l’évaluation au format WHNF, auquel cas 9!1on utilisera la définition de niveau supérieur (!)=seq. Si l'indicateur n'est pas activé, f!_définit un nouvel opérateur (!)et masque la définition de niveau supérieur.

ბიმო
la source
7

ApplicativeDo, 104 octets

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

Essayez-le en ligne!

Avec ApplicativeDo, cela imprime

ZipList {getZipList = [1]}

Sans cela, ça imprime

ZipList {getZipList = []}

ZipListest l'un des rares types dans les bibliothèques de base avec une instance pour Applicativemais pas pour Monad. Il peut y avoir des alternatives plus courtes qui se cachent quelque part.

Zgarb
la source
7

Strict, 87 84 82 octets

-5 octets grâce à dfeuer !

Pourrait être moins de BlockArgumentssauver les parents autour \_->print 1:

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

Exécuter ceci avec -XStrict imprime une impression 1alors que le faire avec -XNoStrict imprimera une 0. Cela utilise par défaut que Haskell est fainéant et qu'il n'est pas nécessaire de l'évaluer error""puisqu'il sait déjà que le résultat sera le même 0lorsque le premier argument correspond (!), ce comportement peut être modifié avec cet indicateur - forçant le moteur d'exécution à évaluer les deux arguments.

Si rien n'est autorisé dans un cas, nous pouvons le réduire à 75 octets en remplaçant le texte principal par (certains octets sont également désactivés par dfeuer ):

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

StrictData, 106 99 93 octets

-15 octets grâce à dfeuer !

Ceci fait fondamentalement la même chose mais fonctionne avec des champs de données:

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

Imprime 1avec l' indicateur -XStrictData et 0avec -XNoStrictData .

Si rien n'est autorisé dans un cas, nous pouvons le réduire à 86 octets en remplaçant le principal par (19 octets désactivés par dfeuer ):

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

Remarque: Toutes les solutions nécessitent un TypeApplicationsensemble.

ბიმო
la source
Vous pouvez facilement le réduire à 98 octets, ce qui correspond exactement à ma solution (très différente). TIO .
dfeuer
En fait, vous pouvez faire encore mieux: au lieu d’imprimer dans le gestionnaire d’exceptions, utilisez simplement pure().
dfeuer
1
@dfeuer: Nice, le D{}truc est plutôt cool! Rasés les uns des autres par utiliser au PartialTypeSignatureslieu de ScopedTypeVariables:)
ბიმო
1
@dfeuer: J'ai jeté un coup d'oeil et essayé plusieurs choses, mais je n'ai jamais utilisé de génériques, alors je ne suis probablement pas la bonne personne.
ბიმო
1
Vous pouvez faire encore mieux avec GHC et -XBlockArguments:main=catch @ErrorCall(p$seq(D$error"")1)\_->p 3
dfeuer
6

ApplicativeDo, 146 octets

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}

Imprime 1 lorsque ApplicativeDo est activé, 0 sinon

Essayez-le en ligne!

oisdk
la source
1
Merci! Ah, je pense que je suis sur une ancienne version de GHC (le "no applicative" était un avertissement sur mon système)
oisdk
3
Utilisez -XDeriveAnyClass pour dériver Applicativeet Showsauvegarder en utilisant la syntaxe d’enregistrement, voyez ceci .
ბიმო
6

BinaryLiterals, 31 à 24 octets

Modifier:

  • -7 octets: H.PWiz a suggéré de l'ajuster davantage en utilisant une seule b12variable.

Un ajustement à la méthode de H.PWiz , évitant l'instance de la fonction.

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

ExtendedDefaultRules, 54 53 octets

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

Imprime ()avec -XExtendedDefaultRuleset 0avec -XNoExtendedDefaultRules.

Cet indicateur est activé par défaut dans GHCi, mais pas dans GHC, ce qui m'a récemment causé une certaine confusion , même si BMO a rapidement été en mesure de vous aider.

Le code ci-dessus est une version par défaut d'un exemple du Guide de l'utilisateur GHC où le type par défaut dans GHCi est expliqué.

-1 octet grâce à Ørjan Johansen !

Laikoni
la source
En regardant ce code emprunté dans le polyglotte (où les parenthèses posent problème), je me suis rappelé que GHC prend en charge la syntaxe plus courte d'un octet toEnum 0::Num a=>Enum a=>a.
Ørjan Johansen
Vous pouvez obtenir jusqu'à 48 octets avec PartialTypeSignatures: main=print(toEnum 0::_=>Num a=>a). De plus, votre lien TIO est obsolète.
dfeuer
6

RebindableSyntax , 25 octets

Je lisais le Guide des extensions de GHC, récemment publié , lorsque j'ai remarqué un guide facile que je ne me souvenais pas avoir vu ici.

main|negate<-id=print$ -1

Nécessite également -XImplicitPrelude, ou bien import Preludedans le code lui-même.

  • -XRebindableSyntax modifie le comportement de certains sucres syntaxiques de Haskell pour permettre de le redéfinir.
  • -1est le sucre syntaxique pour negate 1.
  • Normalement , negatec’est Prelude.negate, mais avec l’extension, c’est "quelle que negatesoit la portée au moment de l’utilisation", qui est définie par id.
  • Comme l'extension est destinée à être utilisée pour remplacer le Preludemodule, elle désactive automatiquement l'importation implicite habituelle de cette dernière, mais d'autres Preludefonctions (comme print) sont nécessaires ici, elle est donc réactivée -XImplicitPrelude.
Ørjan Johansen
la source
6

Strict, 52 octets

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

-XStrict

-XNoStrict

Avec -XStrict, imprime ()un temps supplémentaire.

Merci à @Sriotchilism O'Zaic pour deux octets.

dfeuer
la source
6

StrictData, 58 octets

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

(Les liens sont un peu dépassés; ça va s'arranger.)

-XNoStrictData

-XStrictData

Requiert MagicHash(pour nous permettre d'importer GHC.Extsau lieu de Unsafe.Coerce) et -O(absolument nécessaire, pour permettre le décompactage de petits champs stricts).

With -XStrictData, imprime 3. Sinon, imprime la valeur entière du pointeur (probablement marqué) sur la copie pré-allouée de 3::Integer, qui ne peut éventuellement pas être 3.

Explication

Ce sera un peu plus facile à comprendre avec un peu d’extension, basé sur le type default. Avec les signatures, nous pouvons supprimer l’ajout.

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

De manière équivalente,

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

Pourquoi imprime-t-on 3? Cela semble surprenant! Eh bien, les petites Integervaleurs sont représentées beaucoup comme Ints, qui (avec des données strictes) sont représentées exactement comme Ds. Nous finissons par ignorer la balise indiquant si le nombre entier est petit ou grand positif / négatif.

Pourquoi ne peut-il pas imprimer 3 sans l'extension? Mis à part les raisons d’agencement de la mémoire, un pointeur de données avec des bits faibles (2 inférieurs pour 32 bits, 3 inférieurs pour 64 bits) de 3 doit représenter une valeur générée à partir du troisième constructeur. Dans ce cas, cela nécessiterait un entier négatif .

dfeuer
la source
5

UnboxedTuples, 52 octets

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

Nécessite -XTemplateHaskell. Imprime ConE GHC.Prim.(##)avec -XUnboxedTuples et UnboundVarE ##avec -XNoUnboxedTuples .

Laikoni
la source
Ne devrait-il pas y avoir un autre +16 dans le score pour l'option requise -XTemplateHaskell?
celtschk
2
@celtschk Je ne l'ai pas compté parce que le méta-consensus actuel sur les drapeaux de ligne de commande indique qu'ils ne sont pas comptés mais constituent un nouveau langage. Bien que j'y réfléchisse, je constate que dans le contexte de ce défi qui ne permet que des réponses de Haskell mais également l'utilisation d'autres drapeaux, il est difficile de savoir quoi faire. Je vais demander à OP à ce sujet.
Laikoni
Je ne savais pas que le consensus à ce sujet avait changé. Merci pour le pointeur. Demander le PO est une bonne idée à coup sûr.
celtschk
5

OverloadedLists, 76 bytes

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

Avec -XOverloadedLists, il s'imprime [()]. Avec -XNoOverloadedLists, il imprime[]

Cela nécessite des drapeaux supplémentaires: -XFlexibleInstances,-XIncoherentInstances

H.PWiz
la source
Vous pouvez sortir avec des instances qui se chevauchent.
dfeuer
5

HexFloatLiterals , 49 25 octets

-24 octets grâce à Ørjan Johansen.

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

Imprime 0.0avec -XHexFloatLiteralset 0avec -XNoHexFloatLiterals.

Il n'y a pas de liens TIO car HexFloatLiterals a été ajouté dans ghc 8.4.1, mais TIO contient ghc 8.2.2.

stasoïde
la source
main|(.)<-seq=print$0x0.0évite la dissimulation d'importation.
Ørjan Johansen
main|let _._=0=print$0x0.0pourrait être plus facile pour le polyglotte cependant.
Ørjan Johansen
5

ScopedTypeVariables, 37 octets

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

Cela nécessite également UnicodeSyntax, PartialTypeSignatures, GADTset ExplicitForAll.

Essayez-le en ligne (sans extension)

Essayez-le en ligne (avec extension)

Explication

Les signatures de type partiel servent uniquement à sauvegarder des octets. Nous pouvons les remplir comme suit:

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

Avec les variables de type scoped, le adans le type de 1est contraint à être adans le type de main, ce qui est lui-même contraint à être Float. Sans variables de type ciblées, le type par 1défaut Integer. Puisque Floatet les Integervaleurs sont affichées différemment, nous pouvons les distinguer.

Merci à @ ØrjanJohansen pour ses 19 octets! Il s'est rendu compte qu'il était bien préférable de tirer parti de la différence entre des Showinstances de types numériques différents que des différences d'arithmétique. Il s'est également rendu compte qu'il était normal de laisser le type d ' main"ambiguïté syntaxique" car la contrainte la désambiguise. Le fait de me débarrasser de la fonction locale m'a également libéré pour supprimer la signature de type main( pour la déplacer vers le RHS) et économiser cinq octets supplémentaires.

dfeuer
la source
45 octets
Ørjan Johansen
@ Øjanjohansen, sympa .
dfeuer
@ ØrjanJohansen, devrais-je effectuer le montage ou préférez-vous ajouter le vôtre?
Dfeuer
Editer, c’était une évolution progressive de la vôtre.
Ørjan Johansen
@ ØrjanJohansen, merci, c'était magnifique.
dfeuer
5

DeriveAnyClass, 121 113 octets

Merci à dfeuer pour quelques octets!

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

-XDeriveAnyClass imprime 1alors que -XNoDeriveAnyClass imprime M 0.

Ceci exploite le fait que DeriveAnyClass est la stratégie par défaut lorsque DeriveAnyClass et GeneralizedNewtypeDeriving sont activées, comme vous pouvez le constater dans les avertissements. Ce drapeau se fera un plaisir de générer des implémentations vides pour toutes les méthodes , mais GeneralizedNewtypeDeriving est en fait assez intelligent pour utiliser la mise en œuvre du type sous - jacent et depuis Intest un , Numil ne manquera pas dans ce cas.


Si vous n'imprimez rien si l'indicateur est activé, le remplacement mainpar le suivant serait de 109 octets :

main=print(0::M)`catch`(mempty::SomeException->_)
ბიმო
la source
Au moins dans runhaskell, cela imprime effectivement M 1avec -XDeriveAnyClass, à cause de la paresse ...
cessé de tourner
@ceasedtoturncounterclockwis: Oui dans GHCi aussi bien, mais lors de la compilation sur TIO (et ma machine) et puis l' exécuter résulte 1:)
ბიმო
113 octets
Dfeuer
109 octets
Dfeuer
1
Je l'ai descendu à 104 d'une manière complètement différente, alors j'ai ajouté ma propre réponse.
dfeuer
4

PostfixOperators, 63 octets

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

Essayez-le en ligne (sans extension)

Essayez-le en ligne (avec extension)

Ceci est une version réduite d' un polyglotte Hugs / GHC que j'ai écrit . Voir ce post pour une explication. Merci à @ ØrjanJohansen d’avoir réalisé que j’aurais pu utiliser idun opérateur personnalisé, économisant quatre octets.

dfeuer
la source
idpeut être utilisé à la place de !.
Ørjan Johansen
@ ØrjanJohansen, oui en effet! Cela sauve un cool quatre octets.
dfeuer
3

TemplateHaskell, 140 91 octets

Vient de copier mauke avec de petites modifications. Je ne sais pas ce qui se passe.

-49 octets grâce à Ørjan Johansen.

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

Essayez-le en ligne!

stasoïde
la source
$(...)(pas d'espace) est la syntaxe d'évaluation du modèle lorsque TH est activé, et TupE[]("tuple vide") donne (). UtiliserShow pourrait bien fonctionner pour les polyglottes, bien que pour ce défi particulier, je me sens un peu mal de définir une valeur à imprimer comme une chaîne vide ...
Ørjan Johansen
2

MonomorphismRestriction, 31 29 bytes

Modifier:

  • -2 octets avec une amélioration de H.PWiz
f=(2^)
main=print$f$f(6::Int)

-XMonomorphismRestriction imprime 0. -XNoMonomorphismRestriction imprime 18446744073709551616.

  • Avec la restriction, les deux utilisations de fsont forcées d'être du même type, de sorte que le programme s'imprime en 2^2^6 = 2^64tant que 64 bits Int(sur des plates-formes 64 bits), ce qui déborde 0.
  • Sans cette restriction, le programme est imprimé 2^64en bignum Integer.
Ørjan Johansen
la source
1
Je pense f=(2^);main=print$f$f(64::Int)économiser un octet. Mais cela ne se terminera pas de manière réaliste
H.PWiz
@ H.PWiz Heureusement 64=2^6, ce qui sauve encore un autre octet.
Ørjan Johansen
1

ScopedTypeVariables, 119 97 octets

Vient de copier mauke avec de petites modifications.

Il existe actuellement deux autres réponses pour ScopedTypeVariables: 113 octets par Csongor Kiss et 37 octets par dfeuer . Cette soumission est différente en ce sens qu'elle ne nécessite pas d'autres extensions Haskell.

-22 octets grâce à Ø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)

Essayez-le en ligne!

stasoïde
la source
97 octets (bien que l' IO()/printastuce ne marche pas dans le polyglotte).
Ørjan Johansen le
@ ØrjanJohansen J'ai ajouté ScopedTypeVariables, mais j'ai cassé ExtendedDefaultRules . Comment cela peut-il être corrigé? J'ai déjà eu une telle erreur auparavant, mais je suis incapable d'appliquer votre explication ici. Le code ScopedTypeVariables j'ajouté est ce .
stasoïde le
Je vois, les codes utilisent des astuces similaires par défaut, et ils interfèrent les uns avec les autres. Une solution consiste à laisser le nouveau utiliser une classe plus restreinte que Num. Je pense que class(Show a,Floating a)=>K a where{k::a->String;k=pure$ show(f pi)where f=id::a->a};devrait fonctionner, en utilisant commodément cela Floatet Doubleafficher piavec une précision différente.
Ørjan Johansen le
@ ØrjanJohansen Wow, ça va très bien. Merci.
Stasoïde