Haskell 在lambdas或函数组合(没有中间函数)中有任何消除歧义的方法吗?
考虑以下代码Haskell 在lambdas或函数组合(没有中间函数)中有任何消除歧义的方法吗?,haskell,Haskell,考虑以下代码 {-# 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 :: Hu
{-# 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
由于
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的答案中,使用可以帮助实现无点风格:
{-# 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!
添加到@StéphaneLaurent的答案中,使用可以帮助实现无点风格:
{-# 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]
添加类型签名应强制编译器选择正确的版本 为什么不为所有这些函数添加类型签名?比如:
fh :: [Human] -> [Human]
添加类型签名应强制编译器选择正确的版本 如果我理解正确,你可以使用
\(Human n)->n==“bob”
,但是你的fh4
在语法上是无效的。那么fh3=filter(\h->(name(h::Human))==“bob”)Human
呢?我将编辑我的问题;实际上,我们的想法是,在每个数据类型中有更多的字段,我不能直接在类型上使用(=),但必须使用的name函数them@sandwood:您使用DuplicateRecordFields
扩展名,而不使用humanName
,dogName
声明记录,有什么特殊原因吗,等等?@WillemVanOnsem:是的,我做了一个真正的mcve,剥离了整个画面:简短:我做了一些数据库表到Haskell数据类型(Haskell根据实际数据库生成代码,将一个表映射到Haskell数据类型,每个数据库列有一条记录)。在这个数据库中,我有数百个表,您可以想象,我有几个表具有相同的列名(如“id”、“name”、…)。我不想用表名作为所有表名的前缀,因为我希望表名简单且最接近数据库中的真实列名。如果我理解正确,您可以使用\(Human n)->n==“bob”
,但是您的fh4
在语法上无效。那么fh3=过滤器(\h->(name(h::Human))==“bob”)呢人类
?我将编辑我的问题;实际上,我们的想法是,在每个数据类型中有更多的字段,我不能直接在类型上使用(=),但必须使用的name函数them@sandwood:您使用DuplicateRecordFields
扩展名,而不使用humanName
,dogName
声明记录,有什么特殊原因吗,等等?@WillemVanOnsem:是的,我做了一个真正的mcve,剥离了整个画面:简短:我做了一些数据库表到Haskell数据类型(Haskell根据实际数据库生成代码,将一个表映射到Haskell数据类型,每个数据库列有一条记录)。在这个数据库中,我有数百个表,您可以想象,我有几个表具有相同的列名(如“id”、“name”、…)。我不想用表名作为所有表名的前缀,因为我希望表名保持简单,并且最接近数据库中的实际列名