簡體   English   中英

如何在Haskell中“重載”美元運算符

[英]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.ApplicativeControl.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM