Haskell 类型类和类型签名
我正在试验打字签名。这一个有效:Haskell 类型类和类型签名,haskell,Haskell,我正在试验打字签名。这一个有效: nonz :: (Eq s, Num s, Show s) => ((->) a) s -> a -> Maybe s nonz f v = let w = f v in if w == 0 then Nothing else Just w main = do print $ nonz (+3) 7 print $ nonz (+4) (-4) 但当我将其设置为typeclass时,会出现一个错误: class Nonz
nonz :: (Eq s, Num s, Show s) => ((->) a) s -> a -> Maybe s
nonz f v = let w = f v in if w == 0 then Nothing else Just w
main = do
print $ nonz (+3) 7
print $ nonz (+4) (-4)
但当我将其设置为typeclass时,会出现一个错误:
class Nonz z where
nonz :: (Eq s, Num s, Show s) => z s -> a -> Maybe s
instance Nonz ((->) r) where
nonz f v = let w = f v in if w == 0 then Nothing else Just w
main = do
print $ nonz (+3) 7
print $ nonz (+4) (-4)
类型
r
和a
不匹配。如何将它们联系在一起?如果您打算将Nonz
应用于具有两个参数的类型构造函数,那么您应该相应地编写类。现在,您的类参数具有kind*->*
。您可能希望它具有种类*->*->*->*
你们班
class Nonz z where
nonz :: (Eq s, Num s, Show s) => z s -> a -> Maybe s
建议的替代方案
class Nonz z where
nonz :: (Eq s, Num s, Show s) => z a s -> a -> Maybe s
然后就可以编写您的实例了
instance Nonz (->) where
nonz f v = let w = f v in if w == 0 then Nothing else Just w
如果您打算将
Nonz
应用于具有两个参数的类型构造函数,那么您应该相应地编写类。现在,您的类参数具有kind*->*
。您可能希望它具有种类*->*->*->*
你们班
class Nonz z where
nonz :: (Eq s, Num s, Show s) => z s -> a -> Maybe s
建议的替代方案
class Nonz z where
nonz :: (Eq s, Num s, Show s) => z a s -> a -> Maybe s
然后就可以编写您的实例了
instance Nonz (->) where
nonz f v = let w = f v in if w == 0 then Nothing else Just w
实际上,我想了解函数如何成为函子实例。所以你的回答对我很有帮助。以下是完整的工作示例:
nonz' :: (Eq s, Num s) => (a -> s) -> a -> Maybe s
{-
nonz' :: (Eq s, Num s) => ((->) a s) -> a -> Maybe s
nonz' :: (Eq s, Num s) => ((->) a) s -> a -> Maybe s
-}
nonz' f v = let w = f v in if w == 0 then Nothing else Just w
class Nonz z where
nonz :: (Eq s, Num s) => z a s -> a -> Maybe s
instance Nonz (->) where
nonz f v = let w = f v in if w == 0 then Nothing else Just w
main = do
print $ nonz' (+3) 7
print $ nonz' (+4) (-4)
print $ nonz' length "foo"
print $ nonz' length ""
print $ nonz (+3) 7
print $ nonz (+4) (-4)
print $ nonz length "foo"
print $ nonz length ""
非常感谢。实际上,我想了解函数如何成为函子实例。所以你的回答对我很有帮助。以下是完整的工作示例:
nonz' :: (Eq s, Num s) => (a -> s) -> a -> Maybe s
{-
nonz' :: (Eq s, Num s) => ((->) a s) -> a -> Maybe s
nonz' :: (Eq s, Num s) => ((->) a) s -> a -> Maybe s
-}
nonz' f v = let w = f v in if w == 0 then Nothing else Just w
class Nonz z where
nonz :: (Eq s, Num s) => z a s -> a -> Maybe s
instance Nonz (->) where
nonz f v = let w = f v in if w == 0 then Nothing else Just w
main = do
print $ nonz' (+3) 7
print $ nonz' (+4) (-4)
print $ nonz' length "foo"
print $ nonz' length ""
print $ nonz (+3) 7
print $ nonz (+4) (-4)
print $ nonz length "foo"
print $ nonz length ""
非常感谢。您的代码几乎正确。您可以从
类中的签名中删除a
参数,而只需使nonz
返回z(可能是s)
。z
的内部可以隐藏a
,作为其实现细节的一部分。此外,也不需要Show s
以下是编译时的外观:
class Nonz z where
nonz :: (Eq s, Num s) => z s -> z (Maybe s)
instance Nonz ((->) a) where
nonz f v = let w = f v in if w == 0 then Nothing else Just w
main = do
print $ nonz (+3) 7
print $ nonz (+4) (-4)
这是因为a
变量与Nonz
类无关,因此它可以隐藏在实现中。当实现为((->)a)
时,实例函数的签名将变为:
nonz :: (Eq s, Num s) => ((->) a) s -> ((->) a) (Maybe s)
通过使用中缀符号并删除括号,其与:
nonz :: (Eq s, Num s) => (a -> s) -> a -> Maybe s
您可能会进一步注意到,nonz
的签名现在看起来很像对函子的操作。你是对的。实际上,您可以使用此实现为实现Functor
的任何类型实现Nonz
:
nonz' :: (Eq s, Num s) => s -> Maybe s
nonz' w = if w == 0 then Nothing else Just w
instance Nonz ((->) a) where
nonz = fmap nonz'
现在您可能决定删除Nonz
类,直接使用fmap Nonz'
。您的代码几乎是正确的。您可以从类中的签名中删除a
参数,而只需使nonz
返回z(可能是s)
。z
的内部可以隐藏a
,作为其实现细节的一部分。此外,也不需要Show s
以下是编译时的外观:
class Nonz z where
nonz :: (Eq s, Num s) => z s -> z (Maybe s)
instance Nonz ((->) a) where
nonz f v = let w = f v in if w == 0 then Nothing else Just w
main = do
print $ nonz (+3) 7
print $ nonz (+4) (-4)
这是因为a
变量与Nonz
类无关,因此它可以隐藏在实现中。当实现为((->)a)
时,实例函数的签名将变为:
nonz :: (Eq s, Num s) => ((->) a) s -> ((->) a) (Maybe s)
通过使用中缀符号并删除括号,其与:
nonz :: (Eq s, Num s) => (a -> s) -> a -> Maybe s
您可能会进一步注意到,nonz
的签名现在看起来很像对函子的操作。你是对的。实际上,您可以使用此实现为实现Functor
的任何类型实现Nonz
:
nonz' :: (Eq s, Num s) => s -> Maybe s
nonz' w = if w == 0 then Nothing else Just w
instance Nonz ((->) a) where
nonz = fmap nonz'
现在您可能决定删除Nonz
类,直接使用fmap Nonz'
。作为旁注,Nonz
实际上似乎根本没有使用Show s
约束。您确定需要该约束吗?作为旁注,nonz
实际上似乎根本没有使用Show s
约束。你确定你需要那个约束吗?我很高兴你提到了Functor
。我用这个想法写了你们班的另一个版本。请看我的答案。我很高兴你提到了Functor
。我用这个想法写了你们班的另一个版本。请看我的答案。或[w|w/=0]
,带单体理解。或[w|w/=0]
,带单体理解。