在 lambda 或函数组合(无中间函数)中消除歧义的任何方法



请考虑以下代码

{-# 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]

添加类型签名应强制编译器选择正确的版本。

最新更新