[英]Haskell design best practice for multiple modules assocated with similar set of functions
说函数foo
, bar
noo
是我程序的基础。 此外,尽管foo1
和foo2
仍具有相同的输入和输出类型,但是可以在不同的场景 ( foo1, bar1
, foo2, bar2
等)中以不同的方式实现这些功能。 根据某些输入或配置,程序在某些情况下使用foo1, bar1
,而在另一情况下 ,使用foo2, bar2
。
我可以如上所述定义它们,将后缀(1,2,3 ..)附加到foo, bar, noo
。 但是,这并不好,因为后缀可能很长。 也不允许foo1
与bar1
特殊绑定(与bar2
)。
一种替代方法是将每个方案都视为单独的Module
。 现在foo, bar, noo
每种情况下的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
,可以发现这个职位 ,并在这里 。) Java interface and class
在很多情况下, 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
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.