specializzazione in classi di tipo utilizzando ghc
-
11-09-2019 - |
Domanda
Come posso fare il fuoco 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
Compilare e link:
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
Risultato:
cetin@unique:~/lab/c/linking/demo$ ./hsex2
3.141592653589793"\n"cetin@unique:~/lab/c/linking/demo$
:
atteso:
cetin@unique:~/lab/c/linking/demo$ ./hsex2
3.141592653589793
cetin@unique:~/lab/c/linking/demo$
Come posso fare che regola il fuoco?
Soluzione
Sembra che si desidera sovrapposizione casi , come si desidera avere un instance Out String
che è diverso instance Show a => Out a
che si sovrappone esso.
{-# 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 raccomandazione generale è quello di evitare l'uso di istanze che si sovrappongono e le istanze indecidibili a meno che veramente necessari, come i cambiamenti a typechecking che fanno non sono portatili e possono causare altri problemi.
Modifica
Attuazione-saggio, pensare a dizionario per ogni istanza di una classe. <<
sarà dato il dizionario per l'istanza di Out
che si prevede di utilizzare come parametro nascosto. Dal momento che out
viene guardato da lì, non c'è spazio per il vostro RULE
al fuoco. Se non out
erano in typeclass, e era stato chiamato da una funzione non polimorfica, quindi mi aspetterei il RULE
da abbinare, ma così com'è, non è sorprendente che non funziona.
RULE
/ SPECIALIZE
sono destinate ad essere solo ottimizzazioni, e il codice non dovrebbe cambiare comportamento se lo fanno o non vengono attivati.
Ci ho messo un po 'a capire quello che stavi facendo ... Ti rendi conto che non è Haskell C ++, giusto? I modi in cui viene utilizzato il polimorfismo è molto diversa.