Défi
Trouvez une expression, d'au plus 100 octets, avec la signature de type la plus longue.
Règles
- Toute langue typée statiquement avec inférence de type est autorisée
- Le type doit être non ambigu, mais peut autrement inclure des types sans instances définies. Par exemple
Num [a]
etEq [a]
sont autorisés, même sans instance définie - Aucune importation autre que le minimum requis pour compiler un programme avec STDIN / STDOUT
- Les types infinis ne sont pas autorisés
- Si une réponse a plus d'une expression, une seule peut contribuer au score. Par exemple, bien que le type de signature de la composition soit
(.) :: (b -> c) -> (a -> b) -> a -> c
, ayant un score de 20, la réponse avec 25 copies de(.)\n
aurait un score de 20, pas 500 - L'expression doit être au maximum de 100 octets
- Le score est le nombre de caractères dans la signature de type, à l'exclusion du nom de la fonction et des espaces. Par exemple,
f :: (a -> b) -> a -> b
aurait un score de 12 - Le score le plus élevé gagne!
Exemples
Bien que d'autres langues soient autorisées, les exemples suivants sont en Haskell:
Score: 112
map.map.map.map.map.map.map.map.map.map.map.map.map.map.map.map.map.map.map.map.map.map.map.map.map
f :: (a -> b)
-> [[[[[[[[[[[[[[[[[[[[[[[[[a]]]]]]]]]]]]]]]]]]]]]]]]]
-> [[[[[[[[[[[[[[[[[[[[[[[[[b]]]]]]]]]]]]]]]]]]]]]]]]]
Score: 240
(.).(.).(.).(.).(.).(.).(.).(.).(.).(.).(.).(.).(.).(.).(.).(.).(.).(.).(.).(.).(.).(.).(.).(.).(.)
f :: (b->c)->(a->a1->a2->a3->a4->a5->a6->a7->a8->a9->a10->a11->a12->a13->a14->a15->a16->a17->a18->a19->a20->a21->a22->a23->a24->b)->a1->a2->a3->a4->a5->a6->a7->a8->a9->a10->a11->a12->a13->a14->a15->a16->a17->a18->a19->a20->a21->a22->a23->a24->c
Score: 313
foldl$foldl$foldl$foldl$foldl$foldl$foldl$foldl$foldl$foldl$foldl$foldl$foldl$foldl$foldl$foldl(.)
f :: (Foldable t, Foldable t1, Foldable t2, Foldable t3, Foldable t4,
Foldable t5, Foldable t6, Foldable t7, Foldable t8, Foldable t9,
Foldable t10, Foldable t11, Foldable t12, Foldable t13,
Foldable t14, Foldable t15) =>
(b -> c)
-> t (t1 (t2 (t3 (t4 (t5 (t6 (t7 (t8 (t9 (t10 (t11 (t12 (t13 (t14 (t15 (b
-> b))))))))))))))))
-> b
-> c
Score: 538
lex.show.foldl1.mapM.traverse.sum.mapM.sum.traverse.(.).mapM.scanl.zipWith3((.traverse).(.traverse))
(Num
(a -> ([[c]] -> t3 [[a1 -> f b]]) -> [[c]] -> t3 [[a1 -> f b]]),
Num
(([[c]] -> t3 [[a1 -> f b]])
-> t1 (t2 ([[c]] -> t3 [[a1 -> f b]]))
-> [[c]]
-> t3 [[a1 -> f b]]),
Show
(t (t1 (t2 ([[c]] -> t3 [[a1 -> f b]])))
-> t1 (t2 ([[c]] -> t3 [[a1 -> f b]]))),
Applicative f, Foldable t,
Foldable ((->) (t1 (t2 ([[c]] -> t3 [[a1 -> f b]])) -> a)),
Foldable
((->) (([[c]] -> t3 [[a1 -> f b]]) -> a -> t3 [a1 -> f b])),
Traversable t1, Traversable t2, Traversable t3, Traversable t4,
Traversable t5,
Traversable ((->) (t1 (t2 ([[c]] -> t3 [[a1 -> f b]])))),
Traversable ((->) ([[c]] -> t3 [[a1 -> f b]]))) =>
[(t5 (t4 a1) -> f (t5 (t4 b))) -> c -> a1 -> f b]
-> [(String, String)]
code-challenge
busy-beaver
functional-programming
Michael Klein
la source
la source
Réponses:
Haskell, ~ 2 ^ (2 ^ 18)
Chaque application
f
consiste à doubler approximativement la signature de type en transformant la signature de typeT
en(T,T)
. Par exemple, la composition quadruplef.f.f.f$0
a le typeChaque ligne quadruple le nombre d'applications de
f
, donnant4^9 = 2^18
à la fin. Ainsi, la signature de type a une taille de l'ordre de2^(2^18)
.la source
f x=(x,x,x)
prix d'unn.
dans la dernière ligne donne le score optimal pour cette structure globale.n.
sera plus grand.2^18
vs3 * (2^16)
sauf si j'ai fait une erreur de calcul de l'exponentiation d'origine:2^(4^9)
vs3^((4^8)*3)
(,)
(ou(,,)
) peut être utilisé pour enregistrer certains octets et améliorer le score en utilisant plus den
s.Java, score 17301488
Nécessite la méthode
<T>java.util.Map<T,T>f(T t){return null;}
, qui a été prise en compte dans la limite de 100 octets.f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(1)))))))))))))))))))
La signature de type à la compilation de ceci doit correspondre à ceci.
la source
Haskell avec extensions,⋙ A ( A ( A ( A ( 220 , 0 ) , 0 ) , 0 ) , 0 )
Essayez-le en ligne!
Nécessite
-XDataKinds
,-XPolyKinds
,-XTypeOperators
,-XUndecidableInstances
et-XTypeFamilies
.Un grand merci à Ørjan Johansen, qui a réalisé que rendre le constructeur de nombres naturels infixé et construire les arguments un peu différemment permettait d'économiser deux octets, ce qui laissait juste assez de place pour une autre itération de
#
.De toute évidence, le vérificateur de type abandonnera la vérification de ce programme. Pour avoir une idée générale de ce à quoi ressemblerait la signature (si elle était suffisamment petite pour tenir dans l'univers observable), essayez la beaucoup plus petite
Explication
LaUNE , mais
#
famille de types est étroitement liée à la fonction Ackermann – Péter , communément écrite#
croît considérablement plus rapidement. La fonction Ackermann – Péter est définie#
d'autre part, nous pouvons appelerIci, nous calculons une représentation unaire de
Par calcul direct,B ( B ( B ( B ( 0 , 0 ) , 0 ) , 0 ) , 0 ) = 220 , donc
La définition des nombres naturels,,
(?)
est un peu non standard. Pour économiser de l'espace, nous utilisons(?)
à la fois un type de nombre naturel (au niveau du type) et un type de proxy (au niveau du terme).Je crois que l'un
TypeFamilies
ou l' autre (de façon plus verbeuse et plus obscure)FunctionalDependencies
sont nécessaires pour obtenir le calcul de niveau requis pour atteindre des types vraiment grands.UndecidableInstances
est nécessaire pour contourner la vérification de terminaison très primitive de Haskell. Les autres extensions ne sont nécessaires que pour compresser le code dans le petit espace disponible.la source
#Z
Z
mieux de s'empiler à l'avant que de commencerS(S Z)#S Z
, ou la même chose?#Z
à la fin est le bienvenu.?
enregistrer l'autre, laissant de la place pour le supplément#Z
.A(m,1)
n'était jamais plus grand queA(A(m,0),0)
, et que j'étais sur le point de le remarquer, mais vous veniez juste d'optimiser au point où les options étaient égales. (Aussim+1
n'est jamais plus grand queA(m,0)
.)Haskell, 9 · 2 663552 - 3 (≈ 1,02 · 10 199750 )
Une petite ("petite") amélioration par rapport à 5⋅2 262144 + 5 de xnor . C'est 99 octets.
Comment ça marche
On a
et ainsi de suite, la longueur doublant à peu près pour chacun
(:)
. L'expression donnée correspondo.o.o
à(:).(:).(:).….(:)
2 · 4 6 · 3 4 = 663552 copies de(:)
.Haskell avec
FlexibleContexts
etNoMonomorphismRestriction
, (200 · 4 331776 + 75 · 331776 + 16) / 9 ≈ 2,53 · 10 199750Une petite amélioration par rapport à Bubbler 12 · 2 663552 + 9 · 663552 - 4 ≈ 1,36 · 10 199750 , qui repose également sur ces extensions. Le libellé du défi suggère en quelque sorte qu'il pourrait être acceptable de se fier à eux («Par exemple
Num [a]
etEq [a]
sont autorisés, même sans une instance définie»); Je ne suis pas sûr. C'est 100 octets.Comment ça marche
On a
et ainsi de suite, la longueur quadruplant à peu près pour chacun
(/).(:)
. L'expression donnée correspond-o.o.o
à-(/).(:).(/).(:).….(/).(:)
4 6 · 3 4 = 331776 copies de(/).(:)
.la source
Haskell, 12 · 2 663552 + 9 · 663552 - 4
Encore une petite amélioration par rapport à la réponse d'Anders Kaseorg .
Comment ça marche
Je viens de changer la composition de la fonction
(.)
en division fractionnaire(/)
. LaFractional x
partie de la signature de fonction explose avec la partie principale, donnant un multiplicateur constant légèrement plus élevé.la source
C, 979
f
a la signature:la source
C ++ 11, non compétitif
Je n'arrive presque pas à obtenir moins de 100 octets, mais c'est si proche que je me suis dit que je pourrais le publier de toute façon, dans l'espoir que quelqu'un repère une optimisation.
Voici le prologue, qui coûte 93 octets:
Et l'expression, 9 octets:
Pour illustrer:
Doublement grossissant chaque fois que le nombre augmente.
la source
class
plutôt quetypename
. Je me demande s'il y a un compilateur quelque part qui prend toujours en charge cette formulation pour une compatibilité descendante?C #, 363
Expression:
Signature de type:
Essayez-le en ligne!
la source
Go 1.0 sans
reflect
, 98Les types Go 1.x sont définis statiquement. Voici mon premier essai:
Sur le terrain de jeu Go :
Go 1.9 à l'aide d'alias de type, 2389
Sur le terrain de jeu Go :
Résultat:
Go 1 using
reflect
, 65532Il y a une limite dans le package
reflect
sur la longueur des noms de type:len(name) <= 1<<16-1
J'ai pu atteindre un nom de type de 65532 octets jusqu'à présent avec ce bloc:
Code complet sur le terrain de jeu Go :
Remarques:
x:=
n'est jamais compté.la source
reflect
importation devra être comptéeIdris,> hyper (hyper (hyper (hyper (999999999, 99, 99), 99,99), 99,99), 99,99)
Explication:
Nous définissons une fonction f, calculer un type f (0) n'est que le type d'unité, tandis que f (S (n)) calcule le type d'égalité appliqué à l'argument de fonction "hyperéxé" par lui-même et à f appliqué à n . La dernière ligne est une fonction qui attend une valeur d'un type comme (27 = (4 = (2 = (1 = ()))))) (pour n = 4).
Exemple simple
la source
:Type
?hyper
; pourriez-vous expliquer?hyper
est amplifié beaucoup plus que les autres, je pense que vous voulez que tous / la plupart de ces99
s soient des9
s. (3) En supposant que les$
travaux d'Idris comme Haskell, l'ensemble extérieur de parenthèses aprèsf$
est redondant. (4) Pourriez-vous abrégerhyper
ou cela nécessiterait-il une signature de type elle-même?Haskell, 782
Expression:
Signature de type:
la source
sum
alors(Num a, Foldable t) => t a -> a
Ceylan, 38843546786070481 (~ 4 · 10 16 )
Il s'agit de 49 un-tuples imbriqués, avec un tuple vide à l'intérieur. Le nom court de ce type est en fait le même que la valeur dans ce cas, mais le nom entièrement développé est beaucoup plus long.
Le compilateur de Ceylan fonctionne pour toujours en essayant de compiler cela (le compilateur fonctionnait toujours après 180 minutes) - je vais devoir essayer de calculer la longueur théorique du type.
Le problème ici est qu'un type de tuple à un élément
[X]
est en fait représenté dans le système de types de Ceylan commeTuple<X, X, []>
(le premier paramètre est un supertype pour tous les types d'éléments, le deuxième est le type du premier élément, et le troisième le type de tous sauf les premiers éléments , qui est ici un tuple vide (l'empty
objet, l'instance unique satisfaisant l'interfaceEmpty
)).[]
Est doncempty
,[[]]
estTuple<[], [], []>
=Tuple<empty, empty, empty>
,[[[]]]
estTuple<[[]], [[]], []>
=Tuple<Tuple<[], [], []>, Tuple<[], [], []>, []>
. Et le nom complet inclut les noms des packages, nous n'avons doncceylon.language::Tuple<ceylon.language::Tuple<ceylon.language::empty, ceylon.language::empty, ceylon.language::empty>, ceylon.language::Tuple<ceylon.language::empty, ceylon.language::empty, ceylon.language::empty>, ceylon.language::empty>
que trois niveaux. Et nous voulons aller à 50.Comme il
ceylon.language::empty
contient 22 caractères, et chacunceylon.language::Tuple<?,?,ceylon.language::empty>
ajoute 47 au double du résultat de l'étape précédente, nous obtenonsf(1) = 22
, etf(n) = 2 · f(n-1) + 47
. Cela simplifief(n) = 69 · 2^(n - 1) - 47
et la saisie de 50 nous donne 38843546786070481. Bien sûr, c'est beaucoup plus grand que ce qui tiendrait dans la mémoire de mon ordinateur (8 · 10 9 octets).Bien sûr, le compilateur peut être intelligent et ne pas essayer d'avoir le nom de type entier en mémoire jusqu'à ce que son nom soit demandé.
Voici le programme complet essayant d'imprimer le type:
la source
C # (Visual C # Interactive Compiler) , 99 octets, score 841
Essayez-le en ligne!
Les sorties
la source