Haskell t在实现您的行为时,不要使用上下文,使其不会出现在类型中。类型类提供了方便性和一致性,当您甚至不知道如何编写程序时,这两者都不相关。@josejuan,比在编辑中使用GADT的版本更好的方法是我的答案或Bheklillr的答案中的版本(删除了行为的类型参数
Haskell t在实现您的行为时,不要使用上下文,使其不会出现在类型中。类型类提供了方便性和一致性,当您甚至不知道如何编写程序时,这两者都不相关。@josejuan,比在编辑中使用GADT的版本更好的方法是我的答案或Bheklillr的答案中的版本(删除了行为的类型参数,haskell,polymorphism,Haskell,Polymorphism,t在实现您的行为时,不要使用上下文,使其不会出现在类型中。类型类提供了方便性和一致性,当您甚至不知道如何编写程序时,这两者都不相关。@josejuan,比在编辑中使用GADT的版本更好的方法是我的答案或Bheklillr的答案中的版本(删除了行为的类型参数,因为您不使用它们)。它们是等价的。非常感谢@ReidBarton,两个答案都很好。我走你的路:) interface IBehavior { void foo(); } class AppObject { IBehavior bee; vo
t在实现您的
行为时,不要使用上下文,使其不会出现在类型中。类型类提供了方便性和一致性,当您甚至不知道如何编写程序时,这两者都不相关。@josejuan,比在编辑中使用GADT的版本更好的方法是我的答案或Bheklillr的答案中的版本(删除了行为
的类型参数,因为您不使用它们)。它们是等价的。非常感谢@ReidBarton,两个答案都很好。我走你的路:)
interface IBehavior { void foo(); }
class AppObject { IBehavior bee; void run(); }
...
var app = new AppObject { bee = makeOneOrOtherBehavior(); }
....
class Behavior k a where
behavior :: k -> IO ()
foo :: k -> a -> Bool
...
data BehaviorA
instance Behavior BehaviorA where
behavior _ = print "Behavior A!"
data BehaviorB
instance Behavior BehaviorB where
behavior _ = print "Behavior B!"
data WithBehavior =
WithBehavior { foo :: String
, bee :: forall b . Behavior b => b
}
run :: WithBehavior -> IO ()
run (WithBehavior {..}) = print foo >> behavior bee
selectedBee x = case x of
"A" -> makeBehaviorA
"B" -> makeBehaviorB
...
withBehavior x = makeWithBehavior (selectedBee x)
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE GADTs #-}
import System.Environment
import Control.Applicative
class Behavior k where
behavior' :: k -> IO ()
data BehaviorInstance where
BehaviorInstance :: Behavior b => b -> BehaviorInstance
behavior :: BehaviorInstance -> IO ()
behavior (BehaviorInstance b) = behavior' b
data BehaviorA = BehaviorA
instance Behavior BehaviorA where
behavior' _ = print "Behavior A!"
makeBehaviorA :: BehaviorInstance
makeBehaviorA = BehaviorInstance BehaviorA
data BehaviorB = BehaviorB
instance Behavior BehaviorB where
behavior' _ = print "Behavior B!"
makeBehaviorB :: BehaviorInstance
makeBehaviorB = BehaviorInstance BehaviorB
data WithBehavior =
WithBehavior { foo :: String
, bee :: BehaviorInstance
}
run :: WithBehavior -> IO ()
run (WithBehavior {..}) = print foo >> behavior bee
main = do
n <- head <$> getArgs
let be = case n of
"A" -> makeBehaviorA
_ -> makeBehaviorB
run $ WithBehavior "Foo Message!" be
data Behavior a = Behavior { behavior :: IO (), ... }
behaviorA = Behavior { behavior = print "Behavior A!" }
behaviorB = Behavior { behavior = print "Behavior B!" }
selectedBee x = case x of
"A" -> behaviorA
"B" -> behaviorB
data WithBehavior a = WithBehavior { foo :: String
, bee :: Behavior a }
run :: WithBehavior a -> IO ()
run (WithBehavior {..}) = print foo >> behavior bee
data Behavior k a = Behavior
{ behavior :: IO ()
, foo :: k -> a -> Bool
}
behaviorA :: Behavior String Int
behaviorA = Behavior
{ behavior = putStrLn "Behavior A!"
, foo = \a b -> length a < b
}
behaviorB :: Behavior String Int
behaviorB = Behavior
{ behavior = putStrLn "Behavior B!"
, foo = \a b -> length a > b
}
selectBehavior :: String -> Maybe (Behavior String Int)
selectBehavior "A" = Just behaviorA
selectBehavior "B" = Just behaviorB
selectBehavior _ = Nothing
main :: IO ()
main = do
putStrLn "Which behavior (A or B)?"
selection <- getLine
let selected = selectBehavior selection
maybe (return ()) behavior selected
putStrLn "What is your name?"
name <- getLine
putStrLn "What is your age?"
age <- readLn -- Don't use in real code, you should actually parse things
maybe (return ()) (\bhvr -> print $ foo bhvr name age) selected