Frage

Wie kann ich das genOut / String Feuer machen?

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

Übersetzen und 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

Ergebnis:

cetin@unique:~/lab/c/linking/demo$ ./hsex2
3.141592653589793"\n"cetin@unique:~/lab/c/linking/demo$ 

Erwartet:

cetin@unique:~/lab/c/linking/demo$ ./hsex2
3.141592653589793
cetin@unique:~/lab/c/linking/demo$ 

Wie kann ich diese Regel Feuer machen?

War es hilfreich?

Lösung

Es sieht aus wie Sie überlappende Instanzen , wie Sie wollen eine instance Out String haben, die als instance Show a => Out a unterscheiden, die es überlappt.

{-# 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

Die allgemeine Empfehlung ist die Verwendung von überlappenden Instanzen und unentscheidbar Instanzen zu vermeiden, es sei denn, wirklich erforderlich, da die Änderungen Typprüfung, dass sie machen, sind nicht tragbar und kann andere Probleme verursachen.


Bearbeiten

Die Umsetzung weisen, denken Sie an Wörterbuch für jede Instanz einer Klasse. << wird das Wörterbuch für die Instanz von Out gegeben werden, das erwartet wird, als versteckter Parameter zu verwenden. Da out von dort nachgeschlagen wird, gibt es keinen Platz für Ihre RULE abzufeuern. Wenn out nicht in einer typeclass waren, und wurde aus einer nicht-polymorphe Funktion aufgerufen wird, dann würde ich die RULE erwarten übereinstimmen, aber wie es ist, ist es nicht verwunderlich, dass es nicht funktioniert.

RULE / SPECIALIZE sollen Optimierungen nur sein, und Ihr Code sollte nicht Verhalten ändern, wenn sie es tun oder nicht feuern.

Es dauerte eine Weile zu erkennen, was Sie taten ... Sie erkennen, dass Haskell nicht C ++, nicht wahr? Die Art und Weise, in dem Polymorphismus verwendet wird, ist ganz anders.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top