说函数foo
,bar
noo
是我程序的基础。此外,尽管foo1, bar1
和foo2, bar2
仍然具有相同的输入和输出类型,但是可以在不同的场景(foo1
,foo2
等)中以不同的方式实现这些功能。根据某些输入或配置,该程序在某些情况下使用foo1, bar1
,而在另一种情况下使用foo2, bar2
。
我本可以如上所述定义它们,将后缀(1,2,3 ..)附加到foo, bar, noo
。但是,这并不好,因为后缀可能很长。也不允许foo1
与bar1
(与bar2
进行特殊绑定)。
一种替代方法是将每个方案都视为单独的Module
。现在,每种情况的foo, bar, noo
都很好地结合在一起,避免了丑陋的后缀。但是,当每个Module
一个文件时,这会引入许多文件。这种方法的另一个缺点是,即使它们确实共享一些相似性(例如,三个功能),这些Modules
也是分开完成的。
会喜欢typeclass
解决方案,但我不会想到,因为不同场景的不同foo
具有相同的输入和输出。
我想知道是否有针对此问题的Haskell最佳实践,可以避免上述方法的上述缺点。
foo1 :: Double -> Double
bar1 :: Int -> Int
noo1 :: [Int] -> [Int]
foo2 :: Double -> Double
bar2 :: Int -> Int
noo2 :: [Int] -> [Int]
...
foo9 :: Double -> Double
bar9 :: Int -> Int
noo9 :: [Int] -> [Int]
编辑:我想这与讨论有关,以解释我将如何通过
Java Interface
处理它(有关Java interface
和Haskell typeclass
的一些不错的讨论,但可以在this post和here上找到。)Java interface and class
可能很复杂很多情况下,但是这里的重载实际上是简洁的。interface Scenario {
double foo(double d);
int bar(int i);
Array<int> noo(Array<int> a);
}
class UseScenario {
void use(Scenario ss) {
ss.foo(...);
ss.bar(...);
ss.noo(...);
}
}
class S1 implements Scenario {
double foo(double d) {...};
int bar(int i) {...};
Array<int> noo(Array<int> a) {...};
}
class S2 implements Scenario {
double foo(double d) {...};
int bar(int i) {...};
Array<int> noo(Array<int> a) {...};
}
最佳答案
一种好的方法是将所有功能都放在一个数据类型中。然后,对于每个不同的策略,应具有该类型的不同值。最后,选择一个默认策略,并将实际功能链接到该默认策略(以方便使用)。例如:
module MyModule where
data Strategy = Strategy {
fooWithStrategy :: Double -> Double
, barWithStrategy :: Int -> Int
, nooWithStrategy :: [Int] -> [Int]
}
defaultStrategy :: Strategy
defaultStrategy = Strategy {
fooWithStrategy = (*2)
, barWithStrategy = (+2)
, nooWithStrategy = id
}
foo :: Double -> Double
foo = fooWithStrategy defaultStrategy
bar :: Int -> Int
bar = barWithStrategy defaultStrategy
noo :: [Int] -> [Int]
noo = nooWithStrategy defaultStrategy
tripleStrategy :: Strategy
tripleStrategy = Strategy {
fooWithStrategy = (*3)
, barWithStrategy = (*3)
, nooWithStrategy = \x -> x ++ x ++ x
}
customAddStrategy :: Int -> Strategy
customAddStrategy n = Strategy {
fooWithStrategy = (+ (fromIntegral n))
, barWithStrategy = (+ n)
, nooWithStrategy = (n :)
}
这提供了许多有用的功能:
customAddStrategy
)。您还可以混合和匹配策略,例如newStrat = defaultStrategy { nooWithStrategy = nooWithStrategy tripleStrategy, fooWithStrategy = (*4) }
foo
,bar
和noo
)可用于