【发布时间】:2019-03-13 22:31:33
【问题描述】:
首先,很抱歉,如果这个问题已经被问到,我根本找不到合适的英文术语来表达我的意思。
我想知道 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 ()
我没有找到任何东西,所以我决定创建这种类型类:
{-# 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
【问题讨论】:
-
你看过
uncurry :: (a -> b -> c) -> ((a, b) -> c) -
哦,这很好,但是如何将
uncurry应用于元组中的每个函数?编写uncurryN 次并不是真正的解决方案,因为我们仍然需要为每个函数复制相同的代码。 -
我不熟悉 Xlib,所以也许其他人可以评论一下使用它的规范方法是什么。但是您的
dsp函数可以在某个地方作为普通的辅助函数正常工作(例如curry和uncurry)——您不需要一个类型类。也许看到learnyouahaskell.com/higher-order-functions#curried-functions -
我喜欢你提议的那门课,虽然我发现你会用
x y -> f而不是f x -> y,甚至f -> x, f -> y来代替f -> x, f -> y。 -
@mb21 你的建议会让我创建与元组大小一样多的
dspX函数^^ @leftaroundabout 我对fundep完全陌生,我真的不知道如何决定哪个Fundep 使用。
标签: haskell tuples dollar-sign