首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >图文和类型签名

图文和类型签名
EN

Stack Overflow用户
提问于 2021-05-26 23:40:59
回答 3查看 137关注 0票数 1

我在试验类型签名。这里的这个是这样的:

代码语言:javascript
复制
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)

但当我把它变成一个典型,我就会犯一个错误:

代码语言:javascript
复制
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)

类型ra不匹配。我怎么能把它们绑在一起?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2021-05-27 00:07:34

如果您打算将Nonz应用于带有两个参数的类型构造函数,那么您应该相应地编写类。现在,您的类参数有* -> *。很可能是你想让它有善良的* -> * -> *

你们班

代码语言:javascript
复制
class Nonz z where
    nonz :: (Eq s, Num s, Show s) => z s -> a -> Maybe s

建议的备选方案

代码语言:javascript
复制
class Nonz z where
    nonz :: (Eq s, Num s, Show s) => z a s -> a -> Maybe s

然后可以编写您的实例。

代码语言:javascript
复制
instance Nonz (->) where
    nonz f v = let w = f v in if w == 0 then Nothing else Just w
票数 4
EN

Stack Overflow用户

发布于 2021-05-27 08:58:05

你的代码几乎是正确的。您可以从a中的签名中移除class参数,而只需使nonz返回z (Maybe s)即可。z的内部可以隐藏a作为其实现细节的一部分。此外,Show s也不是必要的。

下面是编译的方式:

代码语言:javascript
复制
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)时,实例函数的签名将变成:

代码语言:javascript
复制
nonz :: (Eq s, Num s) => ((->) a) s -> ((->) a) (Maybe s)

通过使用infix表示法和删除括号,其内容与以下内容相同:

代码语言:javascript
复制
nonz :: (Eq s, Num s) => (a -> s) -> a -> Maybe s

您可能还会注意到,现在nonz的签名看起来很像函子上的一个操作。你应该是对的。通过使用此实现,您实际上可以为实现Nonz的任何类型实现Functor

代码语言:javascript
复制
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'

票数 3
EN

Stack Overflow用户

发布于 2021-05-27 05:55:13

实际上,我想了解函数是如何成为函子实例的。所以你的回答对我很有帮助。下面是完整的工作示例:

代码语言:javascript
复制
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 ""

非常感谢。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67713982

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档