Haskell 类似于 OCaml 中的私人记录
Haskell private records like in OCaml
在 OCaml 模块签名中我可以这样写:
type monotype = private {
monotype_free_variables: StringSet.t Lazy.t;
monotype_description: monotype_description;
}
(注意private
的用法。)
这允许导入我的模块的代码与 monotype_description
等字段进行模式匹配,但不允许导入我的模块的代码构造记录。
我可以在Haskell中编写具有类似访问权限的代码吗?我想在不允许记录构造的情况下针对 monotypeDescription
字段进行模式匹配。
我知道存在 PatternSynonyms
语言扩展,但我不知道如何使用它。如果可用的话,我也更喜欢更简单的解决方案。
在您的模块中:
module MyMod (MyType(), myGetter, j, n) where -- the key is that MyData is not exported
data MyType = MyData (Maybe Int) String
myGetter (MyData x _) = x
j = MyData (Just 5) "abc"
n = MyData Nothing "abc"
在其他地方,进行模式匹配:
f x | Just i <- myGetter x = show i
| otherwise = "nope"
现在 f j
将是 "5"
,f n
将是 "nope"
。
或者,使用 ViewPatterns
扩展名:
{-# LANGUAGE ViewPatterns #-}
f (myGetter -> Just i) = show i
f _ = "nope"
如果至少还允许记录更新(您可以导入或不导入该字段),则无法匹配字段。我认为限制更多是因为没有明显的语法来仅导入访问器...
真正的解决办法是使用PatternSynonyms
。您需要单向模式:
{-# LANGUAGE PatternSynonyms #-}
module MyModule ( Monotype(Monotype) ) where
import Data.Set
data Monotype = MT (Set String) String
pattern Monotype :: Set String -> String -> Monotype
pattern Monotype { monotype_free_variables, monotype_description }
<- MT monotype_free_variables monotype_description
现在,您可以匹配 Monotype { monotype_free_variables, monotype_description }
但不能构造它:
λ> Monotype { monotype_free_variables = f1, monotype_description = f2 } = m1
λ> Monotype f1 f2 = m1
λ> m3 = Monotype { monotype_free_variables = mempty, monotype_description = "" }
<interactive>:3:6: error:
• non-bidirectional pattern synonym ‘Monotype’ used in an expression
• In the expression:
Monotype
{monotype_free_variables = mempty, monotype_description = ""}
In an equation for ‘m3’:
m3
= Monotype
{monotype_free_variables = mempty, monotype_description = ""}
λ> m3 = Monotype mempty ""
<interactive>:4:6: error:
• non-bidirectional pattern synonym ‘Monotype’ used in an expression
• In the expression: Monotype mempty ""
In an equation for ‘m3’: m3 = Monotype mempty ""
在 OCaml 模块签名中我可以这样写:
type monotype = private {
monotype_free_variables: StringSet.t Lazy.t;
monotype_description: monotype_description;
}
(注意private
的用法。)
这允许导入我的模块的代码与 monotype_description
等字段进行模式匹配,但不允许导入我的模块的代码构造记录。
我可以在Haskell中编写具有类似访问权限的代码吗?我想在不允许记录构造的情况下针对 monotypeDescription
字段进行模式匹配。
我知道存在 PatternSynonyms
语言扩展,但我不知道如何使用它。如果可用的话,我也更喜欢更简单的解决方案。
在您的模块中:
module MyMod (MyType(), myGetter, j, n) where -- the key is that MyData is not exported
data MyType = MyData (Maybe Int) String
myGetter (MyData x _) = x
j = MyData (Just 5) "abc"
n = MyData Nothing "abc"
在其他地方,进行模式匹配:
f x | Just i <- myGetter x = show i
| otherwise = "nope"
现在 f j
将是 "5"
,f n
将是 "nope"
。
或者,使用 ViewPatterns
扩展名:
{-# LANGUAGE ViewPatterns #-}
f (myGetter -> Just i) = show i
f _ = "nope"
如果至少还允许记录更新(您可以导入或不导入该字段),则无法匹配字段。我认为限制更多是因为没有明显的语法来仅导入访问器...
真正的解决办法是使用PatternSynonyms
。您需要单向模式:
{-# LANGUAGE PatternSynonyms #-}
module MyModule ( Monotype(Monotype) ) where
import Data.Set
data Monotype = MT (Set String) String
pattern Monotype :: Set String -> String -> Monotype
pattern Monotype { monotype_free_variables, monotype_description }
<- MT monotype_free_variables monotype_description
现在,您可以匹配 Monotype { monotype_free_variables, monotype_description }
但不能构造它:
λ> Monotype { monotype_free_variables = f1, monotype_description = f2 } = m1
λ> Monotype f1 f2 = m1
λ> m3 = Monotype { monotype_free_variables = mempty, monotype_description = "" }
<interactive>:3:6: error:
• non-bidirectional pattern synonym ‘Monotype’ used in an expression
• In the expression:
Monotype
{monotype_free_variables = mempty, monotype_description = ""}
In an equation for ‘m3’:
m3
= Monotype
{monotype_free_variables = mempty, monotype_description = ""}
λ> m3 = Monotype mempty ""
<interactive>:4:6: error:
• non-bidirectional pattern synonym ‘Monotype’ used in an expression
• In the expression: Monotype mempty ""
In an equation for ‘m3’: m3 = Monotype mempty ""