Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 在fmap时防止自定义类型内的错误值_Haskell - Fatal编程技术网

Haskell 在fmap时防止自定义类型内的错误值

Haskell 在fmap时防止自定义类型内的错误值,haskell,Haskell,我想要一个12小时时钟的幺半群 data Clock12Hours = Clock12Hours Int deriving (Show) instance Monoid Clock12Hours where mappend (Clock12Hours x) (Clock12Hours y) = Clock12Hours $ (x + y) `mod` 12 mempty = Clock12Hours 12 当我mappend(时钟12小时4)(时钟12小时10)时,我

我想要一个12小时时钟的幺半群

data Clock12Hours = Clock12Hours Int
    deriving (Show)

instance Monoid Clock12Hours where
    mappend (Clock12Hours x) (Clock12Hours y) = Clock12Hours $ (x + y) `mod` 12
    mempty = Clock12Hours 12
当我
mappend(时钟12小时4)(时钟12小时10)
时,我得到了正确的值-
clock12小时2

我的问题是:

  • 当我
    fmap(id)时钟12小时10
    时,我得到
    时钟12小时10
    。但是,如果我没有提供函子定义(如评论中所阐明的,甚至无法定义),它怎么知道如何fmap呢
  • 当我尝试
    fmap(+1)(时钟12小时10)
    时,我得到一个错误
    没有使用“+”引起的(Num clock12小时)的实例
    -为什么
  • 我的目标是,如果我尝试fmap一些Int操作,它将给出类似于幺半群的结果(例如
    fmap(+4)(clock12hours10)
    将返回
    clock12hours2
    。如何

  • 我没有回答
    1.
    ,因为我无法在GHC 7.10.3上重现错误

    对于
    2.
    :只有使用1个类型参数构造的类型才能是函子,因为
    fmap
    的参数是多态的,而
    Clock12Hours
    的参数不是多态的

    回答
    3.
    :映射操作解压其参数,应用函数并重新打包整个内容。使用此定义,我们得出:

    myMap :: (Int -> Int) -> Clock12Hours -> Clock12Hours
    myMap f (Clock12Hours time) = Clock12Hours (f time)
    
    但现在的问题是,我们可能无法获得12小时的时间,因此我们有两个选项:添加0(
    mappend mempty
    ),或编写一个
    normalize
    函数:

    normalize (Clock12Hours x) = Clock12Hours (x `mod` 12)
    normalize clock = myMap (`mod` 12) clock
    normalize = myMap (`mod` 12)
    

    我没有回答
    1.
    ,因为我无法在GHC 7.10.3上重现错误

    对于
    2.
    :只有使用1个类型参数构造的类型才能是函子,因为
    fmap
    的参数是多态的,而
    Clock12Hours
    的参数不是多态的

    回答
    3.
    :映射操作解压其参数,应用函数并重新打包整个内容。使用此定义,我们得出:

    myMap :: (Int -> Int) -> Clock12Hours -> Clock12Hours
    myMap f (Clock12Hours time) = Clock12Hours (f time)
    
    但现在的问题是,我们可能无法获得12小时的时间,因此我们有两个选项:添加0(
    mappend mempty
    ),或编写一个
    normalize
    函数:

    normalize (Clock12Hours x) = Clock12Hours (x `mod` 12)
    normalize clock = myMap (`mod` 12) clock
    normalize = myMap (`mod` 12)
    

    我想你是想做这样的事:

    {-# LANGUAGE Safe #-}
    module Numeric.IntMod12 (
        IntMod12(), lift1Enum, lift2Enum
    ) where
    
    newtype IntMod12 = IntMod12 Int deriving (Eq, Ord, Show)
    
    instance Enum IntMod12 where
        {-# INLINABLE toEnum #-}
        toEnum i = IntMod12 (mod i 12)
        {-# INLINABLE fromEnum #-}
        fromEnum (IntMod12 i) = i
    
    lift1Enum :: (Enum a, Enum b) => (Int -> Int) -> a -> b
    {-# INLINABLE lift1Enum #-}
    lift1Enum f = \ x -> toEnum (f (fromEnum x))
    
    lift2Enum :: (Enum a, Enum b, Enum c) => (Int -> Int -> Int) -> a -> b -> c
    {-# INLINABLE lift2Enum #-}
    lift2Enum f = \ x y -> toEnum (f (fromEnum x) (fromEnum y))
    
    instance Real IntMod12 where
        {-# INLINABLE toRational #-}
        toRational (IntMod12 i) = toRational i
    
    instance Num IntMod12 where
        {-# INLINABLE fromInteger #-}
        fromInteger i = IntMod12 (fromInteger (mod i 12))
        (+) = lift2Enum (+)
        (-) = lift2Enum (-)
        (*) = lift2Enum (*)
        negate = lift1Enum negate
        abs = id
        signum 0 = 0
        signum _ = 1
    
    instance Integral IntMod12 where
        {-# INLINABLE toInteger #-}
        toInteger (IntMod12 i) = toInteger i
        div = lift2Enum div
        mod = lift2Enum mod
        quot = lift2Enum quot
        rem = lift2Enum rem
        divMod x y = (toEnum d, toEnum m) where
            (d, m) = divMod (fromEnum x) (fromEnum y)
        quotRem x y = (toEnum q, toEnum r) where
            (q, r) = quotRem (fromEnum x) (fromEnum y)
    
    instance Monoid IntMod12 where
        mempty = 0
        mappend = (+)
    

    因为这不是一个
    函子
    (并且不能变成
    函子
    ),所以您必须使用类似
    lift1Enum
    的东西,而不是
    fmap
    ,我想您的意思是这样做的:

    {-# LANGUAGE Safe #-}
    module Numeric.IntMod12 (
        IntMod12(), lift1Enum, lift2Enum
    ) where
    
    newtype IntMod12 = IntMod12 Int deriving (Eq, Ord, Show)
    
    instance Enum IntMod12 where
        {-# INLINABLE toEnum #-}
        toEnum i = IntMod12 (mod i 12)
        {-# INLINABLE fromEnum #-}
        fromEnum (IntMod12 i) = i
    
    lift1Enum :: (Enum a, Enum b) => (Int -> Int) -> a -> b
    {-# INLINABLE lift1Enum #-}
    lift1Enum f = \ x -> toEnum (f (fromEnum x))
    
    lift2Enum :: (Enum a, Enum b, Enum c) => (Int -> Int -> Int) -> a -> b -> c
    {-# INLINABLE lift2Enum #-}
    lift2Enum f = \ x y -> toEnum (f (fromEnum x) (fromEnum y))
    
    instance Real IntMod12 where
        {-# INLINABLE toRational #-}
        toRational (IntMod12 i) = toRational i
    
    instance Num IntMod12 where
        {-# INLINABLE fromInteger #-}
        fromInteger i = IntMod12 (fromInteger (mod i 12))
        (+) = lift2Enum (+)
        (-) = lift2Enum (-)
        (*) = lift2Enum (*)
        negate = lift1Enum negate
        abs = id
        signum 0 = 0
        signum _ = 1
    
    instance Integral IntMod12 where
        {-# INLINABLE toInteger #-}
        toInteger (IntMod12 i) = toInteger i
        div = lift2Enum div
        mod = lift2Enum mod
        quot = lift2Enum quot
        rem = lift2Enum rem
        divMod x y = (toEnum d, toEnum m) where
            (d, m) = divMod (fromEnum x) (fromEnum y)
        quotRem x y = (toEnum q, toEnum r) where
            (q, r) = quotRem (fromEnum x) (fromEnum y)
    
    instance Monoid IntMod12 where
        mempty = 0
        mappend = (+)
    

    因为这不是
    函子
    (并且不能转换为
    函子
    ),您必须使用类似于
    lift1Enum
    的内容,而不是
    fmap

    此类型不是函子,不能成为函子。函子必须是具有1个参数的类型构造函数。GHC版本7.10.3在
    fmap id(时钟12小时10小时)上抛出错误
    。这三个问题毫无意义:你没有也不可能有一个函子,所以我不相信你声称的#1和#2的结果。问题3,忽略函子问题,只需要一个
    Num
    实例,比如
    Clock12Hours
    ,因为
    (+4)::Num a=>a->a
    @amitaibu再次检查
    fmap id>(Clock12Hours 10)
    。在我们看来,它不可能产生任何结果。可能,发布完整的代码和GHCi会话。可能,某些内容的定义与上面发布的内容不同。@amitaibu:函数应用程序在Haskell中是左关联的,因此代码的意思是
    (fmap id Clock12Hours)12
    。这“有效”由于
    Clock12Hours
    数据构造函数的作用类似于一个函数,因此您的代码使用
    实例函子((->)r
    (请参阅)。我想您的意思是编写
    fmap id(Clock12Hours 12)
    ,因为
    (Clock12Hours 12)无法工作
    不是任何类型的
    函子
    。此类型不是函子,不能成为函子。函子必须是带1个参数的类型构造函数。GHC 7.10.3版在
    fmap id(时钟12小时10小时)上抛出错误
    。这三个问题毫无意义:你没有也不可能有一个函子,所以我不相信你声称的#1和#2的结果。问题3,忽略函子问题,只需要一个
    Num
    实例,比如
    Clock12Hours
    ,因为
    (+4)::Num a=>a->a
    @amitaibu再次检查
    fmap id>(Clock12Hours 10)
    。在我们看来,它不可能产生任何结果。可能,发布完整的代码和GHCi会话。可能,某些内容的定义与上面发布的内容不同。@amitaibu:函数应用程序在Haskell中是左关联的,因此代码的意思是
    (fmap id Clock12Hours)12
    。这“有效”由于
    Clock12Hours
    数据构造函数的作用类似于一个函数,因此您的代码使用
    实例函子((->)r
    (请参阅)。我想您的意思是编写
    fmap id(Clock12Hours 12)
    ,因为
    (Clock12Hours 12)无法工作
    不是任何类型的
    Functor
    。因此,在您的安装中,
    fmap id
    根本不起作用?(这对我来说更有意义,因为我不明白它在我的上是如何工作的)。我似乎也有v7.10.3。我可以将
    数据
    更改为其他内容以满足我的需要,但仍然只有Int参数吗(即,
    data Clock12Hours a=Clock12Hours a
    不会将其仅限于
    Int
    )太长了,读不下去了,你可以做,虽然这会破坏你的数据类型的目的,不是吗?你不能让你的类型多态,然后限制它,这是荒谬的。同样,这是已经存在于Haskell。TL;Dr不这样做。所以,在安装时,<代码> FMAP ID <代码>根本不起作用?(这对我来说更有意义,因为我不明白它在我的上是如何工作的)。我似乎也有v7.10.3。我可以将
    数据
    更改为其他内容以满足我的需要,但仍然只有Int参数(即
    数据时钟12hours a=时钟12hours a
    不会将其限制为
    Int
    仅)?