请考虑以下代码
{-# LANGUAGE DuplicateRecordFields #-}
data Human = Human {name :: String } deriving (Show , Eq)
data Dog = Dog {name :: String } deriving (Show , Eq)
humans = [Human "bob" , Human "john", Human "paul"]
-- Working
humanName h = name (h :: Human)
fh = filter ( (=="bob").humanName ) humans
fh' = filter (h -> (humanName h )=="bob" ) humans
-- Ambigous, not compiling
fh2 = filter ( (=="bob").name ) humans
-- Ambigous, not compiling
fh3 = filter (h -> (name h )=="bob" ) humans
-- Not compiling, I don't know if it's an error syntax or if this is impossible
fh4 = filter (h -> (name h)=="bob" (h :: Human) ) humans
有没有办法让 fh2、fh3 或 fh4 工作而无需定义用于消除歧义的命名函数?
由于name
是重复的记录字段,因此您需要指定它应用于哪种类型:
fh3 = filter (h -> (name (h::Human))=="bob") humans
有关详细信息,请参阅复制记录字段。
编辑
否则,在处理重复的记录字段时,我喜欢按以下步骤进行。
{-# LANGUAGE DuplicateRecordFields #-}
data Human = Human {_name :: String } deriving (Show , Eq)
data Dog = Dog {_name :: String } deriving (Show , Eq)
class HasName a where
name :: a -> String
instance HasName Human where
name = _name
instance HasName Dog where
name = _name
然后你可以做
filter (h -> (name h == "bob")) humans
添加到@StéphaneLaurent的答案中,使用TypeApplication
可以帮助实现无点风格:
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE TypeApplications #-}
data Human = Human {_name :: String } deriving (Show , Eq)
data Dog = Dog {_name :: String } deriving (Show , Eq)
class HasName a where
name :: a -> String
instance HasName Human where
name = _name
instance HasName Dog where
name = _name
humans = [Human "bob" , Human "john", Human "paul"]
-- Now you can write it in pointfree style:
fh2 = filter ((=="Bob") . name @Human) humans
-- ^^^^^^ This is a type argument!
为什么不为所有这些函数添加一个类型签名? 比如:
fh :: [Human] -> [Human]
添加类型签名应强制编译器选择正确的版本。