我希望实现保证导出类似一组函数的模块。
以一个例子说明:假设我想翻译一个单词。每个单词都从源语言(比如英语)映射到目标语言(比如西班牙语和俄语)。
我的主应用程序将导入西班牙语和俄语模型并选择默认模型为俄语。我想保证每个模型都具有:
- 一个函数
translateToken :: String -> String
- 一个函数
translatePhrase :: String -> String
其中特定行为被实现。
我该怎么做?
编辑,关于Lee的回答:如何创建使用守卫的函数的记录语法包含数据类型?
-- let's suppose I want to use a function with guards in a record.
-- how can and should i define that?
data Model = Model { translateToken :: String -> String}
-- idea 1) should I define the functions separately, like this?
-- how do I do this in a way that does not clutter the module?
f l
| l == "foo" = "bar"
main :: IO ()
main = print $ translateToken x "foo"
where
x = Model {translateToken=f}
-- idea 2) define the function when creating the record,
-- despite the syntax error, this seems messy:
-- x = Model {name=(f l | l == "foo" = "bar")}
-- idea 3) update the record later
C
作为一个 Java 接口时,你很快会被C
不是一种类型这个事实绊倒,并开始定义一个围绕C
的存在类型,例如data T = forall t. C t => T t
。而这是一个众所周知的 Haskell 反模式。注意:我大多数情况下同意 Luke Palmer 的观点,即这种方式常常过度复杂,与使用带有函数的基本记录相比没有任何收益。但在某些特定情况下,我认为这种“反模式”是合理的。 - chiSpanishTranslation
,RussianTranslation
)。另一个优点是您可以将记录放入集合中并一起操作,而使用类型类会很麻烦。我还认为这更接近面向对象语言中接口的使用,其中行为与接收器耦合,而不是类型。 - Lee[Model]
- 如果您使用类型类,则需要使用存在类型将SpanishTranslation
,RussianTranslation
等放入同一列表中,这更加复杂。类型类用于重载,而不是数据抽象。 - Lee