3

我正在关注本教程,以下示例来自该教程:https ://github.com/hansroland/reflex-dom-inbits/blob/master/tutorial.md

bodyElement :: MonadWidget t m => m ()
bodyElement = el "div" $ do
  el "h2" $ text "Dropdown"
  text "Select country "
  dd <- dropdown 2 (constDyn countries) def
  el "p" $ return ()
  let selItem = result <$> value dd
  dynText selItem

countries :: Map.Map Int T.Text
countries = Map.fromList [(1, "France"), (2, "Switzerland"), (3, "Germany"), (4, "Italy"), (5, "USA")]

result :: Int -> T.Text
result key = "You selected: " <> fromJust (Map.lookup key countries)

我想constDyn countries用一个函数替换上面的函数,该函数采用 sum 类型的类型 (?) 构造函数并将它们用作下拉列表的元素。

例如,如果我有以下总和类型,我希望下拉菜单显示“锻炼”和“跑步”。如果我稍后添加,例如,Solo_WatchPracticeTape下拉菜单会自动添加“观看练习磁带”。

data SoloPersonPracticeType =
        Solo_Workout 
    |   Solo_Run

我推断我需要创建一个函数,将每个 sum 类型与一个字符串相关联,然后创建另一个函数,将所有这些东西变成可以被constDyn. 但我看不到如何实现这一点。

编辑:

我正在尝试这个,但它仍未完成:

displaySoloPersonPracticeType :: SoloPersonPracticeType -> [Char]
displaySoloPersonPracticeType Solo_Workout = "Workout"
displaySoloPersonPracticeType Solo_Run = "Run"

deriving instance Enum SoloPersonPracticeType 
deriving instance Bounded SoloPersonPracticeType 


instance Universe SoloPersonPracticeType where 
    universe = [minBound..]

但我仍然不明白如何constDynbodyElement函数中输入它。

4

1 回答 1

2

类喜欢Universe并且Enum通常是您想要的工具。您实际上想要一种从这些实例生成列表的方法,这很容易:

[(e, show e) | e <- [minBound..]]

这里show假设您的类型有一个Show实例。您可以轻松地将其替换为您自己的自定义“艳丽”事物:

showMyType :: MyType -> Text
showMyType = \case
  MyType_A -> "A"
  MyType_B -> "B"
  ...

最后,您只需将整个列表作为 aDynamic t (Map MyType Text)传递,dropdown如下所示:constDyn (Map.fromList [(e, showMyType e) | e <- [minBound..]])

于 2020-05-18T22:17:36.983 回答