spécialisation dans les classes de type en utilisant GHC
-
11-09-2019 - |
Question
Comment puis-je faire le? Feu genOut / String
module IOStream where
import System.IO
import System.IO.Unsafe
class Out a where
out :: a → String
instance Show a ⇒ Out a where
out = show
outString :: String → String
outString = id
{-# RULES "genOut/String" out = outString #-}
infixl 9 <<, ≪
(≪), (<<) :: Out a ⇒ IO Handle → a → IO Handle
(<<)= (≪)
h ≪ a = do
s ← h
hPutStr s $ out a
return s
cout, cin, cerr :: IO Handle
cout = return stdout
cin = return stdin
cerr = return stderr
endl :: String
endl = "\n"
--infixr 9 ∘ °
(∘) = (.)
(°) = flip (∘)
module Main where
import System.IO
import IOStream
foreign import ccall "pi.h f_" f_ :: IO Double
main :: IO Int
main = do
--putStrLn . show =<< f_
-- ((≪ endl) . (cout ≪)) =<< f_
(cout ≪) ° (≪ endl) =<< f_
return 0
Compile et lien:
cetin@unique:~/lab/c/linking/demo$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 6.10.2
cetin@unique:~/lab/c/linking/demo$ ghc -fglasgow-exts -O2 -ddump-simpl-stats -XUndecidableInstances -O2 iostream.hs main.hs pi_v2.o -o hsex2
==================== FloatOut stats: ====================
0 Lets floated to top level; 1 Lets floated elsewhere; from 3 Lambda groups
==================== FloatOut stats: ====================
0 Lets floated to top level; 0 Lets floated elsewhere; from 5 Lambda groups
==================== Grand total simplifier statistics ====================
Total ticks: 184
40 PreInlineUnconditionally
45 PostInlineUnconditionally
24 UnfoldingDone
8 LetFloatFromLet
4 EtaReduction
57 BetaReduction
6 KnownBranch
11 SimplifierDone
==================== FloatOut stats: ====================
0 Lets floated to top level; 0 Lets floated elsewhere; from 1 Lambda groups
==================== FloatOut stats: ====================
3 Lets floated to top level; 0 Lets floated elsewhere; from 1 Lambda groups
==================== Grand total simplifier statistics ====================
Total ticks: 218
42 PreInlineUnconditionally
57 PostInlineUnconditionally
33 UnfoldingDone
9 LetFloatFromLet
1 EtaReduction
66 BetaReduction
10 KnownBranch
12 SimplifierDone
Résultat:
cetin@unique:~/lab/c/linking/demo$ ./hsex2
3.141592653589793"\n"cetin@unique:~/lab/c/linking/demo$
attendu:
cetin@unique:~/lab/c/linking/demo$ ./hsex2
3.141592653589793
cetin@unique:~/lab/c/linking/demo$
Comment puis-je faire que le feu de la règle?
La solution
On dirait que vous voulez instances se chevauchent , comme vous voulez d'avoir un instance Out String
qui est différent de celui qui chevauche instance Show a => Out a
il.
{-# LANGUAGE FlexibleInstances, TypeSynonymInstances #-}
{-# LANGUAGE OverlappingInstances, UndecidableInstances #-}
class Out a where out :: a -> String
instance Out String where out = id
instance (Show a) => Out a where out = show
La recommandation générale est d'éviter l'utilisation d'instances se chevauchent et les instances indécidables à moins que vraiment nécessaires, les changements à la vérification du type qu'ils font ne sont pas portables et peuvent causer d'autres problèmes.
Modifier
La mise en œuvre sage, pensez à dictionnaire pour chaque instance d'une classe. <<
sera donné le dictionnaire pour l'instance de Out
qu'il est prévu d'utiliser comme paramètre caché. Depuis out
est regardé à partir de là, il n'y a pas de place pour votre RULE
au feu. Si out
n'étaient pas dans une classe de types, et était appelé à partir d'une fonction non polymorphes, je me attends RULE
de match, mais tel qu'il est, ce n'est pas surprenant que cela ne fonctionne pas.
RULE
/ SPECIALIZE
sont censés être des optimisations seulement, et votre code ne devrait pas changer de comportement si elles font ou ne font feu.
Il m'a fallu un certain temps pour réaliser ce que vous faisiez ... vous vous rendez compte que Haskell n'est pas C ++, non? La manière dont le polymorphisme est utilisé est tout à fait différent.