[英]How to “overload” dollar operator in Haskell
首先,對不起,如果已經提出這個問題,我根本找不到合適的英語術語來表達我的意思。
我想知道Haskell中是否有任何類型類代表函數應用程序,以便為不同的數據類型定義多個行為。
使用Graphics.X11.Xlib
包,我遇到了許多不同的函數,要求完全相同的參數。 所以我的想法是將這些函數打包成一個元組(因為它們的返回類型不一樣),並立即將它們全部輸入參數。 像這樣:
import Graphics.X11.Xlib
main = do
display <- openDisplay ":0"
let dScreen = defaultScreen display
(black, white, cMap) =
-- here is where the "parameter dispatch" is needed
(blackPixel, whitePixel, defaultColormap) display dScreen
-- computation
return ()
我沒有找到任何東西,所以我決定創建這種Type類:
{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FunctionalDependencies #-}
import Graphics.X11.Xlib
class Dispatch f x y | x y -> f where
dsp :: f -> x -> y
instance Dispatch (a -> b, a -> c, a -> d) a (b, c, d) where
dsp (f, g, h) x = (f x, g x, h x)
main = do
display <- openDisplay ":0"
let dScreen = defaultScreen display
(black, white, cMap) =
-- here is where the "parameter dispatch" is needed
(blackPixel, whitePixel, defaultColormap) `dsp` display `dsp` dScreen
-- computation
return ()
它工作正常,通過將實例乘以不同的元組大小,可以根據所需的值簡單地添加或刪除“函數元組”中的函數,代碼仍然可以編譯。
但如果沒有這種解決方法,有沒有辦法做到這一點? 我嘗試使用Control.Applicative
或Control.Arrow
但多個參數函數不能很好地結束。
到目前為止,我最好的嘗試是: (,) <$> blackPixel <*> whitePixel
不是一個真正的答案,但這里是你如何將這個想法擴展到真正的“ $
運算符重載”:
{-# LANGUAGE TypeFamilies, FlexibleInstances #-}
import Prelude hiding (($))
infixr 0 $
class Dispatch f where
type Argument f :: *
type Result f :: *
($) :: f -> Argument f -> Result f
instance Dispatch (a -> b) where
type Argument (a->b) = a
type Result (a->b) = b
f $ x = f x
instance (Dispatch x, Dispatch y, Argument x ~ Argument y)
=> Dispatch (x,y) where
type Argument (x,y) = Argument x
type Result (x,y) = (Result x, Result y)
(f,g) $ a = (f $ a, g $ a)
instance ( Dispatch x, Dispatch y, Dispatch z
, Argument x ~ Argument y, Argument y ~ Argument z )
=> Dispatch (x,y,z) where
type Argument (x,y,z) = Argument x
type Result (x,y,z) = (Result x, Result y, Result z)
(f,g,h) $ a = (f $ a, g $ a, h $ a)
main :: IO ()
main = do
print $ ((\x -> ((2*x+),(3*x+)), (**), logBase) $ 2) $ 4
((8.0,10.0),16.0,2.0)
您可以使用liftA
系列函數將多個函數應用於單個參數。 嵌套它們以將許多函數應用於許多參數。 所以:
(b, w, m) = liftA3 (liftA3 (,,)) blackPixel whitePixel defaultColormap display dScreen
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.