специализация в классах типов с использованием ghc
-
11-09-2019 - |
Вопрос
Как я могу запустить 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$
Как я могу заставить это правило работать?
Решение
Похоже, ты хочешь перекрывающиеся экземпляры, так как вы хотите иметь 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++, верно?Способы использования полиморфизма весьма различны.