我知道在Haskell中有两种将接口的规范与其实现分离的方法:
问题2:还有哪些其他方法可以在Haskell中分离接口/实现?
类型类,例如:
- 接口:
RandomGen
- 实现:
StdGen
- 接口:
记录,例如:
问题2:还有哪些其他方法可以在Haskell中分离接口/实现?
类型类,例如:
RandomGen
StdGen
记录,例如:
CanFoo
),而不仅仅是类型签名(a -> Foo
)CanFoo
但带有更多字段);请注意,在这个上下文中,记录只是带有命名字段的命名元组类型。—— 明确传递函数还是隐式传递函数(通过类型类),在概念上已经被证明是一样的[1]。
data Foo = Foo
-- using type classes
class CanFoo a where
foo :: a -> Foo
doFoo :: CanFoo a => a -> IO Foo
doFoo a = do
putStrLn "hello"
return $ foo a
instance CanFoo Int where
foo _ = Foo
main = doFoo 3
-- using explicit instance passing
data CanFoo' a = CanFoo' { foo :: a -> Foo }
doFoo' :: CanFoo' a -> a -> IO Foo
doFoo' cf a = do
putStrLn "hello"
return $ (foo cf) a
intCanFoo = CanFoo { foo = \_ -> Foo }
main' = doFoo' intCanFoo 3
// data Foo = Foo
case object Foo
// data CanFoo t = CanFoo { foo :: t -> Foo }
trait CanFoo[T] { def foo(x : T): Foo }
object CanFoo {
// intCanFoo = CanFoo { foo = \_ -> Foo }
implicit val intCanFoo = new CanFoo[Int] { def foo(_: Int) = Foo }
}
object MyApp {
// doFoo :: CanFoo Int -> Int -> IO ()
def doFoo(someInt: Int)(implicit ev : CanFoo[Int]] = {
println("hello")
ev.foo(someInt)
}
def main(args : List[String]) = {
doFoo(3)
}
}
doFoo'
),您可以启用RecordWildCards
并编写doFoo' CanFoo'{..} a = do { ... ; return (foo a) }
。这使得函数在语法上更加美观,即使记录字段是中缀二元函数也适用(例如data Num a = Num { (+) :: a -> a -> a }
)。 - user2407038
System.Random
的例子中展示的那样使用它们。 - haroldcarr