English 中文(简体)
撰写一名伪装成像和被没收
原标题:Writing an Instance of Functor for a Type-Synonym and Being Confused
  • 时间:2023-08-19 02:27:20
  •  标签:
  • haskell

我对这个棘手问题表示歉意。 我真心是想,但我是一只新鲜事,它显示了这一点。

I m 试图实施一种类似于一般的环形材料,并将其应用于Paul Hudak在《》书中描述的音乐数据结构。 The Haskell School of 音乐. 自然,半群体/大类动物群被遗漏,但我有以下相关法规:

newtype Duo     a b     = Duo     {duo1     :: a} -- A ring-like structure

data Song a =
       Primitive a
     | Song a :+: Song a             -- Composing Music Sequentially
     | Song a :=: Song a deriving Eq -- Composing Music Concurrently (in parallel)

instance Functor Song where
     fmap f (x :+: y)     = fmap f x :+: fmap f y
     fmap f (x :=: y)     = fmap f x :=: fmap f y
     fmap f (Primitive x) = Primitive $ f x

newtype Concurrent a = Concurrent {fromConcurrent :: Song a} deriving (Show)
newtype Sequential a = Sequential {fromSequential :: Song a} deriving (Show)

type Music a = Duo (Maybe (Concurrent a)) (Maybe (Sequential a))

I m attempting to write an instance of Functor for Music, as Duo doesn t have a Functor I thought this wouldn t be a problem.

I wrote the following implementation:

instance Functor Music where
     fmap :: (a -> b) -> Music a -> Music b
     fmap f = Duo . fmap (fmap f . fromConcurrent) . duo1

But I get the following error: • The type synonym ‘Music’ should have 1 argument, but has been given none • In the instance declaration for ‘Functor Music’ | 167 | instance Functor Music where | ^^^^^^^^^^^^^

Perhaps the problem is just that I m essentially writing a Functor for only a Subset of Duo, maybe this can only work if I make music a newtype instead of just a type synonym. I m really hoping to avoid that on account of the already egregious number of wrappers going on in this code, I d really hate to add another. Maybe you all can think of a way to implement a functor for Duo that makes sense, and makes this all work?

One thing I really don t understand is why it let s me make an instance for show:

instance (Show a) => Show (Music a) where
     show (Duo Nothing)               = "Silence"
     show (Duo (Just (Concurrent x))) = show x
问题回答

Unfortunately, this kind of type-level abstraction is not allowed in Haskell. But I think you might have made some sort of conceptual error in your data type design somewhere. Expanding the types, since Duo has only one field, we would have:

Music a ~= Duo (Maybe (Concurrent a)) (Maybe (Sequential a))
        ~= Maybe (Concurrent a)
        ~= Maybe (Song a)

这真是你想要的吗?

在不大可能的情况下,我认为我非常希望切断中间商。

data Music a = Silence | Sound (Song a)
instance Functor Music where
    fmap f Silence = Silence
    fmap f (Sound notes) = Sound (fmap f notes)

If this is the intended behavior but you must keep the middlemen, newtype is the way forward.

In the likely event that this was not how you intended Music to behave, we can probably give you more/better advice, but we d need to know more about what you intend Duo to mean.

Regarding your edit/comment about Show: in your Show instance, you include a type argument to Music. The problem with the Functor instance is exactly the fact that you do not include the argument. In the Show instance, because the argument is available, the compiler can simply expand the type alias, so the line

instance Show a => Show (Music a)

is identical in every way the compiler cares about to the line

instance Show a => Show (Duo (Maybe (Concurrent a)) (Maybe (Sequential a)))

In your Functor instance, though, the compiler cannot expand the type alias, because you have not supplied the type argument. You could imagine adding type-level lambdas to Haskell, so that you could have instance Functor Music mean something like

instance Functor (a -> Duo (Maybe (Concurrent a)) (Maybe (Sequential a)))

but that has some serious problems. The naive way of adding it leads you to need to do higher-order unification during type-checking, which is undecidable.





相关问题
Euler Problem in Haskell -- Can Someone Spot My Error

I m trying my hand at Euler Problem 4 in Haskell. It asks for that largest palindrome formed by multiplying two three-digit numbers. The problem was simple enough, and I thought my Haskell-fu was up ...

How does foldr work?

Can anybody explain how does foldr work? Take these examples: Prelude> foldr (-) 54 [10, 11] 53 Prelude> foldr (x y -> (x+y)/2) 54 [12, 4, 10, 6] 12.0 I am confused about these executions....

Efficient queue in Haskell

How can I efficiently implement a list data structure where I can have 2 views to the head and end of the list, that always point to a head a tail of a list without expensive calls to reverse. i.e: ...

Problem detecting cyclic numbers in Haskell

I am doing problem 61 at project Euler and came up with the following code (to test the case they give): p3 n = n*(n+1) `div` 2 p4 n = n*n p5 n = n*(3*n -1) `div` 2 p6 n = n*(2*n -1) p7 n = n*(5*n -3)...

Ways to get the middle of a list in Haskell?

I ve just started learning about Functional Programming, using Haskel. I m slowly getting through Erik Meijer s lectures on Channel 9 (I ve watched the first 4 so far) and in the 4th video Erik ...

haskell grouping problem

group :: Ord a => [(a, [b])] -> [(a, [b])] I want to look up all pairs that have the same fst, and merge them, by appending all the list of bs together where they have the same a and discarding ...

Closest equivalent to subprocess.communicate in Haskell

I want to do a popen() / python s subprocess.communicate from Haskell - start a program, give it stdin, and get its stdout/stderr. What s the most direct / Haskellish way to do this?

热门标签