специализация в классах типов с использованием GHC - PullRequest
2 голосов
/ 05 июня 2009

Как я могу запустить огонь 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

Компиляция и ссылка:

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

Результат:

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

Ожидаемое:

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

Как я могу заставить это правило сработать?

1 Ответ

4 голосов
/ 05 июня 2009

Похоже, вы хотите перекрывающихся экземпляров , поскольку вы хотите иметь instance Out String, который отличается от instance Show a => Out a, который перекрывает его.

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

Общая рекомендация - избегать использования перекрывающихся экземпляров и неразрешимых экземпляров, если только действительно не требуется, поскольку внесенные ими изменения в проверку типов не переносимы и могут вызвать другие проблемы.


Редактировать

В отношении реализации подумайте о словаре для каждого экземпляра класса. << будет предоставлен словарь для экземпляра Out, который предполагается использовать в качестве скрытого параметра. Поскольку оттуда ищется out, для вашего RULE нет места для стрельбы. Если бы out не было в классе типов и вызывалось из неполиморфной функции, то я ожидал бы, что RULE будет совпадать, но как это не удивительно, что он не работает.

RULE / SPECIALIZE предназначены только для оптимизации, и ваш код не должен изменять поведение, если оно срабатывает или не срабатывает.

Мне потребовалось некоторое время, чтобы понять, что ты делал, и ад; Вы понимаете, что Haskell - это не C ++, верно? Способы использования полиморфизма весьма различны.

...